diff --git a/.appveyor/test.bat b/.appveyor/test.bat
deleted file mode 100755
index 80d6048e..00000000
--- a/.appveyor/test.bat
+++ /dev/null
@@ -1,5 +0,0 @@
-set HOME=%~dp0\tmp
-
-emacs -l test\test-common.el --batch --eval "(progn (set-default-coding-systems 'utf-8) (load-packages))"
-
-emacs -l test\test-common.el --batch --eval "(progn (set-default-coding-systems 'utf-8) (run-fsharp-unit-tests))"
diff --git a/.dir-locals.el b/.dir-locals.el
new file mode 100644
index 00000000..f4b5d5e8
--- /dev/null
+++ b/.dir-locals.el
@@ -0,0 +1,5 @@
+;;; Directory Local Variables
+;;; For more information see (info "(emacs) Directory Variables")
+
+((emacs-lisp-mode . ((indent-tabs-mode . nil)
+		     (fill-column . 120))))
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 00000000..e27a787d
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,11 @@
+## Description
+
+<!-- Add a small description of the PR that you're submitting -->
+
+## How to test
+
+<!-- Please describe how one can test/verify that the PR is working (when applicable) -->
+
+## Related issues
+
+<!-- Point to the relevant issues addressed by this PR -->
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 00000000..9e97395f
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,76 @@
+name: "CI"
+on:
+  pull_request:
+  push:
+    branches:
+      - master
+jobs:
+  gnu-build:
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ubuntu-latest, macos-latest]
+        dotnet: [9.0.x]
+        emacs_version:
+          - 28.2
+          - 29.4
+          - snapshot
+    runs-on: ${{ matrix.os }}
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-dotnet@v4
+        with:
+          dotnet-version: ${{ matrix.dotnet }}
+      - uses: purcell/setup-emacs@master
+        with:
+          version: ${{ matrix.emacs_version }}
+      - name: Install Eldev
+        run: curl -fsSL https://raw.github.com/doublep/eldev/master/webinstall/github-eldev | sh
+      - name: Show dotnet sdks
+        run: dotnet --list-sdks
+      - name: Show dotnet version
+        run: dotnet --info
+      - name: Eldev archives
+        run: |
+          echo "Archives:"
+          eldev archives
+      - name: Eldev dependencies
+        run: |
+          echo "Dependencies:"
+          eldev -v dependencies
+      - name: Test
+        run: |
+          echo "Testing:"
+          eldev -dtT test
+          
+  windows-build:
+    runs-on: windows-latest
+    strategy:
+      fail-fast: false
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-dotnet@v4
+        with:
+          dotnet-version: 9.0.x
+      - name: Show dotnet sdks
+        run: dotnet --list-sdks
+      - name: Show dotnet version
+        run: dotnet --info
+      - name: Set up Emacs on Windows
+        uses: jcs090218/setup-emacs-windows@master
+        with:
+          version: 29.4
+      - name: Install Eldev
+        run: curl.exe -fsSL https://raw.github.com/doublep/eldev/master/webinstall/eldev.bat | cmd /Q
+      - name: Eldev archives
+        run: |
+          echo "Archives:"
+          ~/.local/bin/eldev.bat archives
+      - name: Eldev dependencies
+        run: |
+          echo "Dependencies:"
+          ~/.local/bin/eldev.bat dependencies
+      - name: Test
+        run: |
+          echo "Testing:"
+          ~/.local/bin/eldev.bat -p -dtT test
diff --git a/.gitignore b/.gitignore
index f6d72691..954af474 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 *.elc
 bin
 tmp
+*~
 
 # Useful for doing releases
 emacs-fsharp-mode-bin/
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 67c757a7..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-language: emacs-lisp
-# Emacs fails to build in container-based builds on Travis
-# See https://github.com/travis-ci/travis-ci/issues/9061
-# and https://github.com/moby/moby/issues/22801
-sudo: required
-dist: bionic
-cache:
-  - directories:
-      # Cache stable Emacs binaries (saves 1min per job)
-      - "$HOME/emacs/"
-# Allow Emacs snapshot builds to fail and don’t wait for these as they can take
-# a looooong time
-matrix:
-  fast_finish: true
-  allow_failures:
-    - env: EMACS_VERSION=emacs-snapshot
-env:
-  - EMACS_VERSION=emacs26
-  - EMACS_VERSION=emacs-snapshot
-
-before_install:
-    # Emacs kelleyk PPA
-  - sudo add-apt-repository -y ppa:kelleyk/emacs
-  - sudo apt-get update
-  - sudo apt install $EMACS_VERSION-nox
-  - sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
-  - wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
-  - sudo dpkg -i packages-microsoft-prod.deb
-  - sudo apt-get update
-  - sudo apt-get install apt-transport-https
-  - sudo apt-get update
-  - sudo apt-get install dotnet-sdk-2.1
-  - export PATH="$HOME/bin:$PATH"
-  - export EMACS=$EMACS_VERSION
-  # Download the makefile to emacs-travis.mk
-  - wget 'https://raw.githubusercontent.com/flycheck/emacs-travis/master/emacs-travis.mk'
-  # Install Emacs (according to $EMACS_VERSION) and Cask
-  - make -f emacs-travis.mk install_cask
-  - travis_retry sudo apt-get install -y fsharp
-
-script:
-  - make test
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea2b9989..2e89caca 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,17 @@
+## 1.10 (2019.12-01)
+
+Features:
+  - #210: Remove old FsAutoComplete support (use LSP)
+	- provide eglot (Emacs LSP client) integration and add eglot
+      integration tests (using Emacs buttercup)
+    - Use Cask instead to automate the package development cycle;
+      development, dependencies, testing, building, packaging
+    - Make project.el aware of F# projects
+  - Use Emacs org-mode for README
+Bugfixes:
+    - #68: Indentation Cleanup / SMIE mode not being applied properly
+      (Gastove)
+
 ## 1.9.14 (2019-06-09)
 
 Features:
diff --git a/Cask b/Cask
deleted file mode 100644
index 2a9191a6..00000000
--- a/Cask
+++ /dev/null
@@ -1,9 +0,0 @@
-(source gnu)
-(source melpa)
-
-(package-file "fsharp-mode.el")
-(files "*.el")
-;; FIXME: Use multiple packages: https://github.com/melpa/melpa#example-multiple-packages-in-one-repository ?
-
-(development
- (depends-on "buttercup"))
diff --git a/Eldev b/Eldev
new file mode 100644
index 00000000..6b01e5e6
--- /dev/null
+++ b/Eldev
@@ -0,0 +1,14 @@
+; -*- mode: emacs-lisp; lexical-binding: t -*-
+
+(setq package-lint-main-file "eglot-fsharp.el")
+(setq eldev-project-main-file "eglot-fsharp.el")
+
+(eldev-use-package-archive 'melpa-unstable)
+(eldev-use-package-archive 'gnu)
+(eldev-use-plugin 'autoloads)
+(setq package-archive-priorities
+      '(("melpa-unstable" . 400)
+	("gnu" . 300)))
+
+
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..d6456956
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/LICENSE.md b/LICENSE.md
deleted file mode 100644
index 064244cb..00000000
--- a/LICENSE.md
+++ /dev/null
@@ -1,208 +0,0 @@
-Copyright 2011-2015
-
-
-    Robin Neatherway
-    Jurgen Hurtzel
-    Jason Imison
-    Chris Barrett
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-------------------------------------------------------------
-
-Apache License, Version 2.0
-===========================
-
-Apache License   
-Version 2.0, January 2004    
-http://www.apache.org/licenses/    
-
-### TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-
-**1. Definitions.**
-
- - "License" shall mean the terms and conditions for use, reproduction,
-and distribution as defined by Sections 1 through 9 of this document.
-
- - "Licensor" shall mean the copyright owner or entity authorized by
-the copyright owner that is granting the License.
-
- - "Legal Entity" shall mean the union of the acting entity and all
-other entities that control, are controlled by, or are under common
-control with that entity. For the purposes of this definition,
-"control" means (i) the power, direct or indirect, to cause the
-direction or management of such entity, whether by contract or
-otherwise, or (ii) ownership of fifty percent (50%) or more of the
-outstanding shares, or (iii) beneficial ownership of such entity.
-
- - "You" (or "Your") shall mean an individual or Legal Entity
-exercising permissions granted by this License.
-
- - "Source" form shall mean the preferred form for making modifications,
-including but not limited to software source code, documentation
-source, and configuration files.
-
- - "Object" form shall mean any form resulting from mechanical
-transformation or translation of a Source form, including but
-not limited to compiled object code, generated documentation,
-and conversions to other media types.
-
- - "Work" shall mean the work of authorship, whether in Source or
-Object form, made available under the License, as indicated by a
-copyright notice that is included in or attached to the work
-(an example is provided in the Appendix below).
-
- - "Derivative Works" shall mean any work, whether in Source or Object
-form, that is based on (or derived from) the Work and for which the
-editorial revisions, annotations, elaborations, or other modifications
-represent, as a whole, an original work of authorship. For the purposes
-of this License, Derivative Works shall not include works that remain
-separable from, or merely link (or bind by name) to the interfaces of,
-the Work and Derivative Works thereof.
-
- - "Contribution" shall mean any work of authorship, including
-the original version of the Work and any modifications or additions
-to that Work or Derivative Works thereof, that is intentionally
-submitted to Licensor for inclusion in the Work by the copyright owner
-or by an individual or Legal Entity authorized to submit on behalf of
-the copyright owner. For the purposes of this definition, "submitted"
-means any form of electronic, verbal, or written communication sent
-to the Licensor or its representatives, including but not limited to
-communication on electronic mailing lists, source code control systems,
-and issue tracking systems that are managed by, or on behalf of, the
-Licensor for the purpose of discussing and improving the Work, but
-excluding communication that is conspicuously marked or otherwise
-designated in writing by the copyright owner as "Not a Contribution."
-
- - "Contributor" shall mean Licensor and any individual or Legal Entity
-on behalf of whom a Contribution has been received by Licensor and
-subsequently incorporated within the Work.
-
-**2. Grant of Copyright License.**
-Subject to the terms and conditions of
-this License, each Contributor hereby grants to You a perpetual,
-worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-copyright license to reproduce, prepare Derivative Works of,
-publicly display, publicly perform, sublicense, and distribute the
-Work and such Derivative Works in Source or Object form.
-
-**3. Grant of Patent License.**
-Subject to the terms and conditions of
-this License, each Contributor hereby grants to You a perpetual,
-worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-(except as stated in this section) patent license to make, have made,
-use, offer to sell, sell, import, and otherwise transfer the Work,
-where such license applies only to those patent claims licensable
-by such Contributor that are necessarily infringed by their
-Contribution(s) alone or by combination of their Contribution(s)
-with the Work to which such Contribution(s) was submitted. If You
-institute patent litigation against any entity (including a
-cross-claim or counterclaim in a lawsuit) alleging that the Work
-or a Contribution incorporated within the Work constitutes direct
-or contributory patent infringement, then any patent licenses
-granted to You under this License for that Work shall terminate
-as of the date such litigation is filed.
-
-**4. Redistribution.**
-You may reproduce and distribute copies of the
-Work or Derivative Works thereof in any medium, with or without
-modifications, and in Source or Object form, provided that You
-meet the following conditions:
-
- - You must give any other recipients of the Work or
-    Derivative Works a copy of this License; and
- 
- - You must cause any modified files to carry prominent notices
-    stating that You changed the files; and
-
- - You must retain, in the Source form of any Derivative Works
-    that You distribute, all copyright, patent, trademark, and
-    attribution notices from the Source form of the Work,
-    excluding those notices that do not pertain to any part of
-    the Derivative Works; and
-
- - If the Work includes a "NOTICE" text file as part of its
-    distribution, then any Derivative Works that You distribute must
-    include a readable copy of the attribution notices contained
-    within such NOTICE file, excluding those notices that do not
-    pertain to any part of the Derivative Works, in at least one
-    of the following places: within a NOTICE text file distributed
-    as part of the Derivative Works; within the Source form or
-    documentation, if provided along with the Derivative Works; or,
-    within a display generated by the Derivative Works, if and
-    wherever such third-party notices normally appear. The contents
-    of the NOTICE file are for informational purposes only and
-    do not modify the License. You may add Your own attribution
-    notices within Derivative Works that You distribute, alongside
-    or as an addendum to the NOTICE text from the Work, provided
-    that such additional attribution notices cannot be construed
-    as modifying the License.
-
-You may add Your own copyright statement to Your modifications and
-may provide additional or different license terms and conditions
-for use, reproduction, or distribution of Your modifications, or
-for any such Derivative Works as a whole, provided Your use,
-reproduction, and distribution of the Work otherwise complies with
-the conditions stated in this License.
-
-**5. Submission of Contributions.**
-Unless You explicitly state otherwise,
-any Contribution intentionally submitted for inclusion in the Work
-by You to the Licensor shall be under the terms and conditions of
-this License, without any additional terms or conditions.
-Notwithstanding the above, nothing herein shall supersede or modify
-the terms of any separate license agreement you may have executed
-with Licensor regarding such Contributions.
-
-**6. Trademarks.**
-This License does not grant permission to use the trade
-names, trademarks, service marks, or product names of the Licensor,
-except as required for reasonable and customary use in describing the
-origin of the Work and reproducing the content of the NOTICE file.
-
-**7. Disclaimer of Warranty.**
-Unless required by applicable law or
-agreed to in writing, Licensor provides the Work (and each
-Contributor provides its Contributions) on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-implied, including, without limitation, any warranties or conditions
-of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-PARTICULAR PURPOSE. You are solely responsible for determining the
-appropriateness of using or redistributing the Work and assume any
-risks associated with Your exercise of permissions under this License.
-
-**8. Limitation of Liability.**
-In no event and under no legal theory,
-whether in tort (including negligence), contract, or otherwise,
-unless required by applicable law (such as deliberate and grossly
-negligent acts) or agreed to in writing, shall any Contributor be
-liable to You for damages, including any direct, indirect, special,
-incidental, or consequential damages of any character arising as a
-result of this License or out of the use or inability to use the
-Work (including but not limited to damages for loss of goodwill,
-work stoppage, computer failure or malfunction, or any and all
-other commercial damages or losses), even if such Contributor
-has been advised of the possibility of such damages.
-
-**9. Accepting Warranty or Additional Liability.**
-While redistributing
-the Work or Derivative Works thereof, You may choose to offer,
-and charge a fee for, acceptance of support, warranty, indemnity,
-or other liability obligations and/or rights consistent with this
-License. However, in accepting such obligations, You may act only
-on Your own behalf and on Your sole responsibility, not on behalf
-of any other Contributor, and only if You agree to indemnify,
-defend, and hold each Contributor harmless for any liability
-incurred by, or claims asserted against, such Contributor by reason
-of your accepting any such warranty or additional liability.
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 75a67d82..00000000
--- a/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-all: build
-export EMACS ?= emacs
-EMACSFLAGS = -L .
-CASK = cask
-VERSION = $(shell git describe --tags --abbrev=0 | sed 's/^v//')
-PKG = fsharp-mode
-
-elpa-$(EMACS):
-	$(CASK) install
-	$(CASK) update
-	touch $@
-
-test/eglot-tests.el:
-	curl -o eglot-tests.el https://raw.githubusercontent.com/joaotavora/eglot/master/eglot-tests.el
-
-elpa: elpa-$(EMACS)
-
-build: elpa version
-	$(CASK) build
-
-version:
-	$(EMACS) --version
-
-test/Test1/restored:
-	dotnet restore test/Test1
-	touch test/Test1/restored
-
-test: version build test/eglot-tests.el test/Test1/restored
-	$(CASK) exec buttercup -L . -L ./test --traceback full
-
-clean:
-	rm -f .depend elpa-$(EMACS) $(OBJECTS) $(PKG)-autoloads.el
-
-elpaclean: clean
-	rm -f elpa*
-	rm -rf .cask # Clean packages installed for development
-
-run-$(PKG): elpa
-	cask exec $(EMACS) -Q -L . --eval "(require '$(PKG))"
-
diff --git a/README.org b/README.org
index b34b066e..85839f17 100644
--- a/README.org
+++ b/README.org
@@ -1,5 +1,6 @@
 [[http://melpa.org/#/fsharp-mode][file:http://melpa.org/packages/fsharp-mode-badge.svg]]
-[[https://travis-ci.org/fsharp/emacs-fsharp-mode][file:https://travis-ci.org/fsharp/emacs-fsharp-mode.png]]
+[[https://stable.melpa.org/#/fsharp-mode][file:https://stable.melpa.org/packages/fsharp-mode-badge.svg]]
+[[https://github.com/fsharp/emacs-fsharp-mode/actions][file:https://github.com/fsharp/emacs-fsharp-mode/workflows/CI/badge.svg]]
 * fsharp-mode
 
 Provides support for the F# language in Emacs. Includes the following features:
@@ -13,20 +14,18 @@ Provides support for the F# language in Emacs. Includes the following features:
   - Jump to definition [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html][Find Identifier References]] (Xref)
 
 ** LSP mode
-Previous versions of =fsharp-mode= (mis)used a second repository [[https://github.com/rneatherway/emacs-fsharp-mode-bin][emacs-fsharp-mode-bin]] to distribute =fsautocomplete.exe= and =fsharp-mode= together.
 
-The current version of =fsharp-mode= installs =fsautocomplete.exe= automatically via  [eglot-fsharp](https://github.com/joaotavora/eglot) (part of this repo) or 
-[lsp-mode](https://github.com/emacs-lsp/lsp-mode) (untested).
+The current version of =fsharp-mode= installs =fsautocomplete.exe=
+automatically via =eglot-fsharp.el= (part of this mono repo, [[https://melpa.org/#/eglot-fsharp][eglot-fsharp
+on melpa]]) or [[https://github.com/emacs-lsp/lsp-mode][lsp-mode]] (untested).
 
-=fsharp-mode= is tested with Emacs 26.1+ and NET Core 2.1 (LTS)
+=fsharp-mode= is tested with Emacs 27.1+ and NET Core 6 (LTS)
 
 ** Installation
 
-*** Package (*OUTDATED*)
+*** Package
 
-*Currently the MELPA package is outdated*! ATM it still refers to  [[https://github.com/rneatherway/emacs-fsharp-mode-bin][emacs-fsharp-mode-bin]]!
-
-=fsharp-mode= is available on [MELPA](https://melpa.org) and can
+=fsharp-mode= is available on [[https://melpa.org][MELPA]] and can
 be installed using the built-in package manager.
 
 If you're not already using MELPA, add the following to your init.el:
@@ -45,7 +44,7 @@ If you're not already using MELPA, add the following to your init.el:
   (require 'fsharp-mode)
 #+END_SRC
 
-If you are a user of [use-package](https://github.com/jwiegley/use-package) you can instead do
+If you are a user of [[https://github.com/jwiegley/use-package][use-package]] you can instead do
 
 #+BEGIN_SRC elisp
 (use-package fsharp-mode
@@ -63,18 +62,19 @@ I recommend to use [[https://cask.github.io/why-cask.html][Cask]]. Add this to y
 
 ** Eglot integration
 
-=fsharp-eglot= is part of this package and provides integration to [[https://github.com/joaotavora/eglot][Eglot]] Emacs LSP client:
+The =eglot-fsharp= integration is not part of [[https://melpa.org/#/fsharp-mode][fsharp-mode on melpa]].
 
-   - Automatic =fsautocomplete= download
-   - Workaround for non-LSP standard-compliant
+It is available via the seperate package [[https://melpa.org/#/eglot-fsharp][eglot-fsharp on melpa]].
 
 Add to your config:
 #+BEGIN_SRC elisp
-(require 'fsharp-eglot)
+(require 'eglot-fsharp)
 #+END_SRC
 
 and execute =M-x eglot=
 
+With eglot running use `xref-find-definitions` (bound to =M-.= pr. default) to go to definition. Completions are accessable via. `completion-at-point` (or a completion backend ex. company-mode [[https://melpa.org/#/company]])
+
 
 ** Projects
 
@@ -155,6 +155,17 @@ Because the F# language is sensitive to indentation, you might wan't to highligh
 =fsharp-mode= is still under development, so you may encounter some
 issues. Please report them so we can improve things! Open an issue on [[https://github.com/fsharp/emacs-fsharp-mode/][Github]].
 
+*** No autocompletion in FSX files
+
+The root cause is documented in this Ionide issue:  [[https://github.com/ionide/ionide-vscode-fsharp/issues/1244][4.2.0 - No auto complete or typechecking in FSX files]]
+
+As a workaround can add a reference to the facade netstandard assembly (path is platform/SDK-dependent).
+
+On Arch Linux using [[https://aur.archlinux.org/packages/dotnet-sdk-lts-bin][dotnet sdk lts]] add this to your =fsx= file:
+#+BEGIN_SRC fsharp
+#r "/opt/dotnet/sdk/2.1.801/ref/netstandard.dll"
+#+END_SRC
+
 *** Project file issues
 
 If your project file does not seem to be being parsed correctly, so
@@ -172,8 +183,8 @@ This project is maintained by the
 [[http://fsharp.org/][F# Software Foundation]], with the repository hosted
 on [[https://github.com/fsharp/emacs-fsharp-mode][GitHub]].
 
-Pull requests are welcome. Please run the test-suite with =make
-test= before submitting a pull request.
+Pull requests are welcome. Please run the test-suite with [[https://doublep.github.io/eldev/][Eldev]] =eldev -dtT test=
+before submitting a pull request.
 
 *** Maintainers
 
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index 67f25e2a..00000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-environment:
-  FSACVERSION: 0.34.0
-  FSharpBinding_BlockingTimeout: 1000
-  FSharpBinding_MaxTimeout: 10000
-matrix:
-  fast_finish: true
-install:
-  - ps: Start-FileDownload "https://github.com/fsharp/FSharp.AutoComplete/releases/download/$env:FSACVERSION/fsautocomplete.zip"
-  - ps: 7z x fsautocomplete.zip -oemacs-fsharp-mode\bin | select-string -notmatch "ing  "
-  - ps: iex (new-object net.webclient).downloadstring('https://get.scoop.sh')
-  - ps: scoop install coreutils
-  - ps: scoop install make
-  - ps: scoop install grep
-  - ps: scoop install unzip
-  - ps: scoop bucket add extras
-  - ps: scoop install emacs
-build_script:
-  - cmd: .\.appveyor\test.bat
-test: off
- 
diff --git a/eglot-fsharp.el b/eglot-fsharp.el
index ca6b86cc..1ca79404 100644
--- a/eglot-fsharp.el
+++ b/eglot-fsharp.el
@@ -1,10 +1,12 @@
-;;; eglot-fsharp.el --- Lua eglot integration                     -*- lexical-binding: t; -*-
+;;; eglot-fsharp.el --- fsharp-mode eglot integration                     -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019  Jürgen Hötzel
+;; Copyright (C) 2019-2024  Jürgen Hötzel
 
-;; Author: Jürgen Hötzel <juergen@archlinux.org>
-;; Package-Requires: ((eglot "1.4"))
+;; Author: Jürgen Hötzel <juergen@hoetzel.info>
+;; Package-Requires: ((emacs "27.1") (eglot "1.4") (fsharp-mode "1.10") (jsonrpc "1.0.14"))
+;; Version: 1.10
 ;; Keywords: languages
+;; URL: https://github.com/fsharp/emacs-fsharp-mode
 
 ;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
@@ -34,92 +36,196 @@
   :link '(url-link "https://github.com/fsharp/FsAutoComplete")
   :group 'eglot)
 
+(defcustom eglot-fsharp-server-path "~/.dotnet/tools/"
+  "Path to the location of FsAutoComplete."
+  :group 'eglot-fsharp
+  :risky t)
+
 (defcustom eglot-fsharp-server-install-dir
   (locate-user-emacs-file "FsAutoComplete/")
   "Install directory for FsAutoComplete."
   :group 'eglot-fsharp
   :risky t
-  :type 'directory)
+  :type '(choice directory (const :tag "Use dotnet default for tool-path" nil)))
 
-(defcustom eglot-fsharp-server-version "0.38.1"
-  "FsAutoComplete version."
+(defcustom eglot-fsharp-server-version 'latest
+  "FsAutoComplete version to install or update."
   :group 'eglot-fsharp
   :risky t
-  :type 'string)
-
-(defcustom eglot-fsharp-server-runtime
-  (if (executable-find "dotnet")
-      'net-core
-    'net-framework)
-  "The .NET runtime to use."
+  :type '(choice
+          (const :tag "Latest release" latest)
+          (string :tag "Version string")))
+
+(defcustom eglot-fsharp-server-args '("--adaptive-lsp-server-enabled")
+  "Arguments for the fsautocomplete command when using `eglot-fsharp'."
+  :type '(repeat string))
+
+(defcustom eglot-fsharp-fsautocomplete-args '(
+                                              :automaticWorkspaceInit t
+                                              :abstractClassStubGeneration t
+				              :abstractClassStubGenerationMethodBody
+				              "failwith \"Not Implemented\""
+				              :abstractClassStubGenerationObjectIdentifier "this"
+				              :addFsiWatcher nil
+				              :codeLenses (:references (:enabled t)
+							               :signature (:enabled t))
+				              :disableFailedProjectNotifications nil
+				              :dotnetRoot ""
+				              :enableAdaptiveLspServer t
+				              :enableAnalyzers nil
+				              :enableMSBuildProjectGraph nil
+				              :enableReferenceCodeLens t
+				              :excludeProjectDirectories [".git" "paket-files" ".fable" "packages" "node_modules"]
+				              :externalAutocomplete nil
+				              :fsac (:attachDebugger nil
+                                                                     :cachedTypeCheckCount 200
+				                                     :conserveMemory nil
+				                                     :dotnetArgs nil
+				                                     :netCoreDllPath ""
+				                                     :parallelReferenceResolution nil
+				                                     :silencedLogs nil)
+				              :fsiExtraParameters nil
+				              :fsiSdkFilePath ""
+				              :generateBinlog nil
+				              :indentationSize 4
+				              :inlayHints (:disableLongTooltip nil
+								               :enabled t
+								               :parameterNames t
+								               :typeAnnotations t)
+				              :inlineValues (:enabled nil
+							              :prefix "//")
+				              :interfaceStubGeneration t
+				              :interfaceStubGenerationMethodBody "failwith \"Not Implemented\""
+				              :interfaceStubGenerationObjectIdentifier "this"
+				              :keywordsAutocomplete t
+				              :lineLens (:enabled "replaceCodeLens"
+					                          :prefix " // ")
+				              :linter t
+				              :pipelineHints (:enabled t
+							               :prefix " // ")
+				              :recordStubGeneration t
+				              :recordStubGenerationBody "failwith \"Not Implemented\""
+				              :resolveNamespaces t
+				              :saveOnSendLastSelection nil
+				              :simplifyNameAnalyzer t
+				              :smartIndent nil
+				              :suggestGitignore t
+				              :suggestSdkScripts t
+				              :unionCaseStubGeneration t
+				              :unionCaseStubGenerationBody "failwith \"Not Implemented\""
+				              :unusedDeclarationsAnalyzer t
+				              :unusedOpensAnalyzer t
+				              :verboseLogging nil
+				              :workspaceModePeekDeepLevel 4
+				              :workspacePath "")
+  "Arguments for the fsautocomplete workspace configuration."
   :group 'eglot-fsharp
-  :type '(choice (const :tag "Use .Net Core" net-core)
-                 (const :tag "Use .Net Framework" net-framework)))
+  :risky t
+  )
 
 (defun eglot-fsharp--path-to-server ()
   "Return FsAutoComplete path."
-  (file-truename (concat eglot-fsharp-server-install-dir
-			 (if (eq eglot-fsharp-server-runtime 'net-core)
-			     "netcore/fsautocomplete.dll"
-			   "netframework/fsautocomplete.exe"))))
-
-(defun eglot-fsharp--maybe-install ()
+  (let ((base (if eglot-fsharp-server-install-dir
+                  (concat eglot-fsharp-server-install-dir "netcore/")
+                eglot-fsharp-server-path)))
+    (expand-file-name (concat base "fsautocomplete" (if (eq system-type 'windows-nt) ".exe" "")))))
+
+;; cache to prevent repetitive queries
+(defvar eglot-fsharp--latest-version nil "Latest fsautocomplete.exe version string.")
+
+(defun eglot-fsharp--latest-version ()
+  "Return latest fsautocomplete.exe version."
+  (let* ((json (with-temp-buffer (url-insert-file-contents "https://azuresearch-usnc.nuget.org/query?q=fsautocomplete&prerelease=false&packageType=DotnetTool")
+			         (json-parse-buffer)))
+         (versions (gethash "versions" (aref (gethash "data" json) 0))))
+    (gethash "version" (aref versions (1- (length versions))))))
+
+(defun eglot-fsharp--installed-version ()
+  "Return version string of fsautocomplete."
+  (with-temp-buffer
+    (if eglot-fsharp-server-install-dir
+        (process-file "dotnet" nil t nil "tool" "list" "--tool-path" (file-name-directory (eglot-fsharp--path-to-server)))
+      (process-file "dotnet" nil t nil "tool" "list" "-g"))
+    (goto-char (point-min))
+    (when (search-forward-regexp "^fsautocomplete[[:space:]]+\\([0-9\.]*\\)[[:space:]]+" nil t)
+      (match-string 1))))
+
+(defun eglot-fsharp-current-version-p (version)
+  "Return t if the installation is up-to-date compared to VERSION string."
+  (and (file-exists-p (concat (file-remote-p default-directory) (eglot-fsharp--path-to-server)))
+       (equal version (eglot-fsharp--installed-version))))
+
+(defun eglot-fsharp--install-core (version)
+  "Download and install fsautocomplete as a dotnet tool at version VERSION in `eglot-fsharp-server-install-dir'."
+  (let* ((default-directory (concat (file-remote-p default-directory)
+                                    (file-name-directory (eglot-fsharp--path-to-server))))
+         (stderr-file (make-temp-file "dotnet_stderr"))
+         (local-tool-path (or (file-remote-p default-directory 'localname) default-directory))
+         (process-file-uninstall-args (if eglot-fsharp-server-install-dir
+                                          (list "dotnet" nil `(nil ,stderr-file) nil "tool" "uninstall" "fsautocomplete" "--tool-path" local-tool-path)
+                                        (list "dotnet" nil `(nil ,stderr-file) nil "tool" "uninstall" "-g" "fsautocomplete")))
+         (process-file-install-args (if eglot-fsharp-server-install-dir
+                                        (list "dotnet" nil `(nil ,stderr-file) nil "tool" "install" "fsautocomplete" "--tool-path" local-tool-path "--version" version)
+                                      (list "dotnet" nil `(nil ,stderr-file) nil "tool" "install" "fsautocomplete" "-g" "--version" version))))
+    (make-directory default-directory t)
+    (condition-case err
+        (progn
+          (unless (or (eglot-fsharp-current-version-p version) (not (eglot-fsharp--installed-version)))
+            (message "Uninstalling fsautocomplete version %s" (eglot-fsharp--installed-version))
+            (unless (zerop (apply #'process-file process-file-uninstall-args))
+              (error  "'dotnet tool uninstall fsautocomplete ... failed")))
+          (unless (zerop (apply #'process-file process-file-install-args))
+            (error "'dotnet tool install fsautocomplete --tool-path %s --version %s' failed" default-directory  version)))
+      (error
+       (let ((stderr (with-temp-buffer
+                       (insert-file-contents stderr-file)
+                       (buffer-string))))
+         (delete-file stderr-file)
+         (signal (car err) (format "%s: %s" (cdr err) stderr)))))
+    (message "Installed fsautocomplete to %s" (eglot-fsharp--path-to-server))))
+
+(defun eglot-fsharp--maybe-install (&optional version)
   "Downloads F# compiler service, and install in `eglot-fsharp-server-install-dir'."
-  (make-directory (file-name-directory (eglot-fsharp--path-to-server)) t)
-  (let* ((url (format "https://ci.appveyor.com/api/projects/fsautocomplete/fsautocomplete/artifacts/bin/pkgs/fsautocomplete%szip?branch=master"
-		      (if (eq eglot-fsharp-server-runtime 'net-core)
-			  ".netcore."
-			".")))
-	 (exe (eglot-fsharp--path-to-server))
-	 (zip (concat (file-name-directory exe) (file-name-nondirectory url)))
-	 (gnutls-algorithm-priority
-	  (if (and (not gnutls-algorithm-priority)
-			  (boundp 'libgnutls-version)
-			  (>= libgnutls-version 30603)
-			  (version<= emacs-version "26.2"))
-		     "NORMAL:-VERS-TLS1.3"
-		   gnutls-algorithm-priority)))
-    (unless (file-exists-p exe)
-      (url-copy-file url zip t)
-      ;; FIXME: Windows
-      (let ((default-directory (file-name-directory (eglot-fsharp--path-to-server))))
-	(unless (zerop (call-process "unzip" nil nil nil "-x" zip))
-	  (error "Failed to unzip %s" zip))))))
-
- ;;;###autoload
+  (unless eglot-fsharp-server-install-dir
+    (make-directory (concat (file-remote-p default-directory)
+                            (file-name-directory (eglot-fsharp--path-to-server))) t))
+  (let* ((version (or version (if (eq eglot-fsharp-server-version 'latest)
+				  (eglot-fsharp--latest-version)
+				eglot-fsharp-server-version))))
+    (unless (eglot-fsharp-current-version-p version)
+      (eglot-fsharp--install-core version))))
+
+;;;###autoload
 (defun eglot-fsharp (interactive)
-"Return `eglot' contact when FsAutoComplete is installed.
+  "Return `eglot' contact when FsAutoComplete is installed.
 Ensure FsAutoComplete is installed (when called INTERACTIVE)."
-  (unless (or (file-exists-p (eglot-fsharp--path-to-server)) (not interactive))
-    (eglot-fsharp--maybe-install))
-  (when (file-exists-p (eglot-fsharp--path-to-server))
-    (cons 'eglot-fsautocomplete
-	  `(,(if (eq eglot-fsharp-server-runtime 'net-core)
-		 "dotnet"
-	       ;; FIXME: Windows
-	       "mono") ,(eglot-fsharp--path-to-server) "--background-service-enabled"))))
+  (when interactive (eglot-fsharp--maybe-install))
+  (cons 'eglot-fsautocomplete
+        (if (file-remote-p default-directory)
+            `("sh" ,shell-command-switch ,(concat "cat|"  (mapconcat #'shell-quote-argument
+                                                                     (cons (eglot-fsharp--path-to-server) eglot-fsharp-server-args) " ")))
+          (cons (eglot-fsharp--path-to-server) eglot-fsharp-server-args))))
 
 
 (defclass eglot-fsautocomplete (eglot-lsp-server) ()
   :documentation "F# FsAutoComplete langserver.")
 
-(cl-defmethod eglot-initialization-options ((server eglot-fsautocomplete))
+(cl-defmethod eglot-initialization-options ((_server eglot-fsautocomplete))
   "Passes through required FsAutoComplete initialization options."
-  '(:automaticWorkspaceInit t))
+  eglot-fsharp-fsautocomplete-args)
 
 ;; FIXME: this should be fixed in FsAutocomplete
-(cl-defmethod xref-backend-definitions :around ((type symbol) _identifier)
+(cl-defmethod xref-backend-definitions :around ((_type symbol) _identifier)
   "FsAutoComplete breaks spec and and returns error instead of empty list."
   (if (eq major-mode 'fsharp-mode)
       (condition-case err
-	  (cl-call-next-method)
-	(jsonrpc-error
-	 (when (equal (cadddr err) '(jsonrpc-error-message . "Could not find declaration"))
-	   nil)))
+          (cl-call-next-method)
+        (jsonrpc-error
+         (not (equal (cadddr err) '(jsonrpc-error-message . "Could not find declaration")))))
     (when (cl-next-method-p)
       (cl-call-next-method))))
 
 (add-to-list 'eglot-server-programs `(fsharp-mode . eglot-fsharp))
 
 (provide 'eglot-fsharp)
-;;; eglot-fsharp.el ends herep
+;;; eglot-fsharp.el ends here
diff --git a/fsharp-mode-font.el b/fsharp-mode-font.el
index 8f0b3e2b..0af65b23 100644
--- a/fsharp-mode-font.el
+++ b/fsharp-mode-font.el
@@ -28,9 +28,6 @@
 
 ;;; Code:
 
-;; (require 'fsharp-mode)
-;; (require 'dash)
-
 (defgroup fsharp-ui nil
   "F# UI group for the defcustom interface."
   :prefix "fsharp-ui-"
@@ -64,97 +61,97 @@ with initial value INITVALUE and optional DOCSTRING."
      (defvar ,sym ,init ,docstring)))
 
 (def-fsharp-compiled-var fsharp-shebang-regexp
-  "\\(^#!.*?\\)\\([A-Za-z0-9_-]+\\)$"
-  "Capture the #! and path of a shebag in one group and the
+                         "\\(^#!.*?\\)\\([A-Za-z0-9_-]+\\)$"
+                         "Capture the #! and path of a shebag in one group and the
   executable in another.")
 
 (def-fsharp-compiled-var fsharp-access-control-regexp
-  "private\\s-+\\|internal\\s-+\\|public\\s-+"
-  "Match `private', `internal', or `public', followed by a space,
+                         "private\\s-+\\|internal\\s-+\\|public\\s-+"
+                         "Match `private', `internal', or `public', followed by a space,
   with no capture.")
 
 (def-fsharp-compiled-var fsharp-access-control-regexp-noncapturing
-  (format "\\(?:%s\\)" fsharp-access-control-regexp)
-  "Same as `fsharp-access-control-regexp', but captures")
+                         (format "\\(?:%s\\)" fsharp-access-control-regexp)
+                         "Same as `fsharp-access-control-regexp', but captures")
 
 (def-fsharp-compiled-var fsharp-inline-rec-regexp
-  "inline\\s-+\\|rec\\s-+"
-  "Match `inline' or `rec', followed by a space.")
+                         "inline\\s-+\\|rec\\s-+"
+                         "Match `inline' or `rec', followed by a space.")
 
 (def-fsharp-compiled-var fsharp-inline-rec-regexp-noncapturing
-  (format "\\(?:%s\\)" fsharp-inline-rec-regexp)
-  "Match `inline' or `rec', followed by a space, with no capture.")
+                         (format "\\(?:%s\\)" fsharp-inline-rec-regexp)
+                         "Match `inline' or `rec', followed by a space, with no capture.")
 
 (def-fsharp-compiled-var fsharp-valid-identifier-regexp
-  "[A-Za-z0-9_']+"
-  "Match a normal, valid F# identifier -- alphanumeric characters
+                         "[A-Za-z0-9_']+"
+                         "Match a normal, valid F# identifier -- alphanumeric characters
   plus ' and underbar. Does not capture")
 
 (def-fsharp-compiled-var fsharp-function-def-regexp
-  (concat "\\<\\(?:let\\|and\\|with\\)\\s-+"
-          fsharp-inline-rec-regexp-noncapturing "?"
-          fsharp-access-control-regexp-noncapturing "*"
-          (format "\\(%s\\)" fsharp-valid-identifier-regexp)
-          "\\(?:\\s-+[A-Za-z_]\\|\\s-*(\\)" ;; matches function arguments or open-paren; unclear why 0-9 not in class
-          ))
+                         (concat "\\<\\(?:let\\|and\\|with\\)\\s-+"
+                                 fsharp-inline-rec-regexp-noncapturing "?"
+                                 fsharp-access-control-regexp-noncapturing "*"
+                                 (format "\\(%s\\)" fsharp-valid-identifier-regexp)
+                                 "\\(?:\\s-+[A-Za-z_]\\|\\s-*(\\)" ;; matches function arguments or open-paren; unclear why 0-9 not in class
+                                 ))
 
 (def-fsharp-compiled-var fsharp-pattern-function-regexp
-  (concat "\\<\\(?:let\\|and\\)\\s-+"
-          fsharp-inline-rec-regexp-noncapturing "?"
-          fsharp-access-control-regexp-noncapturing "*"
-          (format "\\(%s\\)" fsharp-valid-identifier-regexp)
-          "\\s-*=\\s-*function")
-  "Matches an implicit matcher, eg let foo m = function | \"cat\" -> etc.")
+                         (concat "\\<\\(?:let\\|and\\)\\s-+"
+                                 fsharp-inline-rec-regexp-noncapturing "?"
+                                 fsharp-access-control-regexp-noncapturing "*"
+                                 (format "\\(%s\\)" fsharp-valid-identifier-regexp)
+                                 "\\s-*=\\s-*function")
+                         "Matches an implicit matcher, eg let foo m = function | \"cat\" -> etc.")
 
 ;; Note that this regexp is used for iMenu. To font-lock active patterns, we
 ;; need to use an anchored match in fsharp-font-lock-keywords.
 (def-fsharp-compiled-var fsharp-active-pattern-regexp
-  (concat "\\<\\(?:let\\|and\\)\\s-+"
-          fsharp-inline-rec-regexp-noncapturing "?"
-          fsharp-access-control-regexp-noncapturing "*"
-          "(\\(|[A-Za-z0-9_'|]+|\\))\\(?:\\s-+[A-Za-z_]\\|\\s-*(\\)"))
+                         (concat "\\<\\(?:let\\|and\\)\\s-+"
+                                 fsharp-inline-rec-regexp-noncapturing "?"
+                                 fsharp-access-control-regexp-noncapturing "*"
+                                 "(\\(|[A-Za-z0-9_'|]+|\\))\\(?:\\s-+[A-Za-z_]\\|\\s-*(\\)"))
 
 (def-fsharp-compiled-var fsharp-member-access-regexp
-  "\\<\\(?:override\\|member\\|abstract\\)\\s-+"
-  "Matches members declarations and modifiers on classes.")
+                         "\\<\\(?:override\\|member\\|abstract\\)\\s-+"
+                         "Matches members declarations and modifiers on classes.")
 
 (def-fsharp-compiled-var fsharp-member-function-regexp
-  (concat fsharp-member-access-regexp
-          fsharp-inline-rec-regexp-noncapturing "?"
-          fsharp-access-control-regexp-noncapturing "*"
-          "\\(?:" fsharp-valid-identifier-regexp "\\.\\)?"
-          "\\(" fsharp-valid-identifier-regexp "\\)")
-  "Captures the final identifier in a member function declaration.")
+                         (concat fsharp-member-access-regexp
+                                 fsharp-inline-rec-regexp-noncapturing "?"
+                                 fsharp-access-control-regexp-noncapturing "*"
+                                 "\\(?:" fsharp-valid-identifier-regexp "\\.\\)?"
+                                 "\\(" fsharp-valid-identifier-regexp "\\)")
+                         "Captures the final identifier in a member function declaration.")
 
 (def-fsharp-compiled-var fsharp-overload-operator-regexp
-  (concat fsharp-member-access-regexp
-          fsharp-inline-rec-regexp-noncapturing "?"
-          fsharp-access-control-regexp-noncapturing "*"
-          "\\(([!%&*+-./<=>?@^|~]+)\\)")
-  "Match operators when overloaded by a type/class.")
+                         (concat fsharp-member-access-regexp
+                                 fsharp-inline-rec-regexp-noncapturing "?"
+                                 fsharp-access-control-regexp-noncapturing "*"
+                                 "\\(([!%&*+-./<=>?@^|~]+)\\)")
+                         "Match operators when overloaded by a type/class.")
 
 (def-fsharp-compiled-var fsharp-constructor-regexp
-  (concat "^\\s-*"
-          fsharp-access-control-regexp-noncapturing "*"
-          "\\<\\(new\\) *(.*)[^=]*=")
-  "Matches the `new' keyword in a constructor")
+                         (concat "^\\s-*"
+                                 fsharp-access-control-regexp-noncapturing "*"
+                                 "\\<\\(new\\) *(.*)[^=]*=")
+                         "Matches the `new' keyword in a constructor")
 
 (def-fsharp-compiled-var fsharp-type-def-regexp
-  (concat "^\\s-*\\<\\(?:type\\|inherit\\)\\s-+"
-          fsharp-access-control-regexp-noncapturing "*" ;; match access control 0 or more times
-          "\\([A-Za-z0-9_'.]+\\)"))
+                         (concat "^\\s-*\\<\\(?:type\\|inherit\\)\\s-+"
+                                 fsharp-access-control-regexp-noncapturing "*" ;; match access control 0 or more times
+                                 "\\([A-Za-z0-9_'.]+\\)"))
 
 (def-fsharp-compiled-var fsharp-var-or-arg-regexp
-  "\\_<\\([A-Za-z_][A-Za-z0-9_']*\\)\\_>")
+                         "\\_<\\([A-Za-z_][A-Za-z0-9_']*\\)\\_>")
 
 (def-fsharp-compiled-var fsharp-explicit-field-regexp
-  (concat "^\\s-*\\(?:val\\|abstract\\)\\s-*\\(?:mutable\\s-+\\)?"
-          fsharp-access-control-regexp-noncapturing "*" ;; match access control 0 or more times
-          "\\([A-Za-z_][A-Za-z0-9_']*\\)\\s-*:\\s-*\\([A-Za-z_][A-Za-z0-9_'<> \t]*\\)"))
+                         (concat "^\\s-*\\(?:val\\|abstract\\)\\s-*\\(?:mutable\\s-+\\)?"
+                                 fsharp-access-control-regexp-noncapturing "*" ;; match access control 0 or more times
+                                 "\\([A-Za-z_][A-Za-z0-9_']*\\)\\s-*:\\s-*\\([A-Za-z_][A-Za-z0-9_'<> \t]*\\)"))
 
 (def-fsharp-compiled-var fsharp-attributes-regexp
-  "\\(\\[<[A-Za-z0-9_]+[( ]?\\)\\(\".*\"\\)?\\()?>\\]\\)"
-  "Match attributes like [<EntryPoint>]; separately groups contained strings in attributes like [<Attribute(\"property\")>]")
+                         "\\(\\[<[A-Za-z0-9_]+[( ]?\\)\\(\".*\"\\)?\\()?>\\]\\)"
+                         "Match attributes like [<EntryPoint>]; separately groups contained strings in attributes like [<Attribute(\"property\")>]")
 
 ;; F# makes extensive use of operators, many of which have some kind of
 ;; structural significance.
@@ -167,16 +164,27 @@ with initial value INITVALUE and optional DOCSTRING."
 ;; |                         -- match / type expressions
 
 (def-fsharp-compiled-var fsharp-operator-quote-regexp
-  "\\(<@\\{1,2\\}\\)\\(?:.*\\)\\(@\\{1,2\\}>\\)"
-  "Font lock <@/<@@ and @>/@@> operators.")
+                         "\\(<@\\{1,2\\}\\)\\(?:.*\\)\\(@\\{1,2\\}>\\)"
+                         "Font lock <@/<@@ and @>/@@> operators.")
 
 (def-fsharp-compiled-var fsharp-operator-pipe-regexp
-  "<|\\{1,3\\}\\||\\{1,3\\}>"
-  "Match the full range of pipe operators -- |>, ||>, |||>, etc.")
+                         "<|\\{1,3\\}\\||\\{1,3\\}>"
+                         "Match the full range of pipe operators -- |>, ||>, |||>, etc.")
+
+(def-fsharp-compiled-var fsharp-custom-operator-with-pipe-regexp
+                         (let ((op-chars "!%&\\*\\+\\-\\./<=>@\\^~") ;; all F# custom operator chars except for `|`
+                               (backward-pipe "<|\\{1,3\\}")
+                               (forward-pipe "|\\{1,3\\}>")
+                               (alt "\\|"))
+                           (concat "[" op-chars "|]*" backward-pipe "[" op-chars  "]+"
+                                   alt "[" op-chars "|]+" backward-pipe "[" op-chars  "]*"
+                                   alt "[" op-chars  "]*" forward-pipe  "[" op-chars "|]+"
+                                   alt "[" op-chars  "]+" forward-pipe  "[" op-chars "|]*"))
+                         "Match operators that contains pipe sequence -- <|>, |>>, <<|, etc.")
 
 (def-fsharp-compiled-var fsharp-operator-case-regexp
-  "\\s-+\\(|\\)[A-Za-z0-9_' ]"
-  "Match literal | in contexts like match and type declarations.")
+                         "\\s-+\\(|\\)[A-Za-z0-9_' ]"
+                         "Match literal | in contexts like match and type declarations.")
 
 (defvar fsharp-imenu-generic-expression
   `((nil                 ,(concat "^\\s-*" fsharp-function-def-regexp) 1)
@@ -207,52 +215,52 @@ with initial value INITVALUE and optional DOCSTRING."
 
 ;; Preprocessor directives (3.3)
 (def-fsharp-compiled-var fsharp-ui-preproessor-directives
-  '("#if" "#else" "#endif" "#light"))
+                         '("#if" "#else" "#endif" "#light"))
 
 ;; Compiler directives (12.4)
 (def-fsharp-compiled-var fsharp-ui-compiler-directives
-  '("#nowarn" "#load" "#r" "#reference" "#I"
-    "#Include" "#q" "#quit" "#time" "#help"))
+                         '("#nowarn" "#load" "#r" "#reference" "#I"
+                           "#Include" "#q" "#quit" "#time" "#help"))
 
 ;; Lexical matters (18.4)
 (def-fsharp-compiled-var fsharp-ui-lexical-matters
-  '("#indent"))
+                         '("#indent"))
 
 ;; Line Directives (3.9)
 (def-fsharp-compiled-var fsharp-ui-line-directives
-  '("#line"))
+                         '("#line"))
 
 ;; Identifier replacements (3.11)
 (def-fsharp-compiled-var fsharp-ui-identifier-replacements
-  '("__SOURCE_DIRECTORY__" "__SOURCE_FILE__" "__LINE__"))
+                         '("__SOURCE_DIRECTORY__" "__SOURCE_FILE__" "__LINE__"))
 
-;; F# keywords (3.4)
+;; F# keywords (5.0)
 (def-fsharp-compiled-var fsharp-ui-fsharp-threefour-keywords
-  '("abstract" "and" "as" "assert" "base" "begin"
-    "class" "default" "delegate" "do" "do!" "done"
-    "downcast" "downto" "elif" "else" "end"
-    "exception" "extern" "false" "finally" "for" "fun"
-    "function" "global" "if" "in" "inherit" "inline"
-    "interface" "internal" "lazy" "let" "let!"
-    "match" "member" "module" "mutable" "namespace"
-    "new" "not" "null" "of" "open" "or" "override"
-    "private" "public" "rec" "return" "return!"
-    "select" "static" "struct" "then" "to" "true"
-    "try" "type" "upcast" "use" "use!"  "val" "void"
-    "when" "while" "with" "yield" "yield!"))
+                         '("abstract" "and" "and!" "as" "assert" "base" "begin"
+                           "class" "default" "delegate" "do" "do!" "done"
+                           "downcast" "downto" "elif" "else" "end"
+                           "exception" "extern" "false" "finally" "for" "fun"
+                           "function" "global" "if" "in" "inherit" "inline"
+                           "interface" "internal" "lazy" "let" "let!"
+                           "match" "match!" "member" "module" "mutable" "namespace"
+                           "new" "not" "null" "of" "open" "or" "override"
+                           "private" "public" "rec" "return" "return!"
+                           "select" "static" "struct" "then" "to" "true"
+                           "try" "type" "upcast" "use" "use!"  "val" "void"
+                           "when" "while" "with" "yield" "yield!"))
 
 ;; "Reserved because they are reserved in OCaml"
 (def-fsharp-compiled-var fsharp-ui-ocaml-reserved-words
-  '("asr" "land" "lor" "lsl" "lsr" "lxor" "mod" "sig"))
+                         '("asr" "land" "lor" "lsl" "lsr" "lxor" "mod" "sig"))
 
 ;; F# reserved words for future use
 (def-fsharp-compiled-var fsharp-ui-reserved-words
-  '("atomic" "break" "checked" "component" "const"
-    "constraint" "constructor" "continue" "eager"
-    "event" "external" "fixed" "functor" "include"
-    "method" "mixin" "object" "parallel" "process"
-    "protected" "pure" "sealed" "tailcall" "trait"
-    "virtual" "volatile"))
+                         '("atomic" "break" "checked" "component" "const"
+                           "constraint" "constructor" "continue" "eager"
+                           "event" "external" "fixed" "functor" "include"
+                           "method" "mixin" "object" "parallel" "process"
+                           "protected" "pure" "sealed" "tailcall" "trait"
+                           "virtual" "volatile"))
 
 ;; RMD 2016-09-30 -- This was pulled out separately with the following comment
 ;; when I got here. Not clear to me why it's on it's own, or even precisely what
@@ -262,21 +270,21 @@ with initial value INITVALUE and optional DOCSTRING."
 ;; Workflows not yet handled by fsautocomplete but async
 ;; always present
 (def-fsharp-compiled-var fsharp-ui-async-words
-  '("async")
-  "Just the word async, in a list.")
+                         '("async")
+                         "Just the word async, in a list.")
 
 (def-fsharp-compiled-var fsharp-ui-word-list-regexp
-  (regexp-opt
-   `(,@fsharp-ui-async-words
-     ,@fsharp-ui-compiler-directives
-     ,@fsharp-ui-fsharp-threefour-keywords
-     ,@fsharp-ui-identifier-replacements
-     ,@fsharp-ui-lexical-matters
-     ,@fsharp-ui-ocaml-reserved-words
-     ,@fsharp-ui-preproessor-directives
-     ,@fsharp-ui-reserved-words
-     ,@fsharp-ui-line-directives)
-   'symbols))
+                         (regexp-opt
+                          `(,@fsharp-ui-async-words
+                            ,@fsharp-ui-compiler-directives
+                            ,@fsharp-ui-fsharp-threefour-keywords
+                            ,@fsharp-ui-identifier-replacements
+                            ,@fsharp-ui-lexical-matters
+                            ,@fsharp-ui-ocaml-reserved-words
+                            ,@fsharp-ui-preproessor-directives
+                            ,@fsharp-ui-reserved-words
+                            ,@fsharp-ui-line-directives)
+                          'symbols))
 
 (defconst fsharp-font-lock-keywords
   (eval-when-compile
@@ -300,6 +308,7 @@ with initial value INITVALUE and optional DOCSTRING."
         nil nil
         (1 font-lock-function-name-face)
         (2 'fsharp-ui-operator-face)))
+      (,fsharp-custom-operator-with-pipe-regexp . 'fsharp-ui-generic-face)
       (,fsharp-operator-pipe-regexp . 'fsharp-ui-operator-face)
       (,fsharp-member-function-regexp 1 font-lock-function-name-face)
       (,fsharp-overload-operator-regexp 1 font-lock-function-name-face)
@@ -373,16 +382,14 @@ with initial value INITVALUE and optional DOCSTRING."
                                    'syntax-table (string-to-syntax "."))
                 (put-text-property (match-beginning 0) (match-end 0)
                                    'syntax-table (string-to-syntax "|"))
-                nil)))
-        )
+                nil))))
 
        (t ; Then we are in a triple-quoted string
         (when (re-search-forward "\"\"\"" end 'move)
           (put-text-property (- (match-beginning 0) 1) (match-beginning 0)
                              'syntax-table (string-to-syntax "."))
           (put-text-property (match-beginning 0) (match-end 0)
-                             'syntax-table (string-to-syntax "|")))
-        )))))
+                             'syntax-table (string-to-syntax "|"))))))))
 
 (provide 'fsharp-mode-font)
 
diff --git a/fsharp-mode-structure.el b/fsharp-mode-structure.el
index 4d913e04..30376a39 100644
--- a/fsharp-mode-structure.el
+++ b/fsharp-mode-structure.el
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2010 Laurent Le Brun
 
 ;; Author: 2010-2011 Laurent Le Brun <laurent@le-brun.eu>
-;; Maintainer: Robin Neatherway <robin.neatherway@gmail.com>
+;; Maintainer: Jürgen Hötzel <juergen@hoetzel.info>
 ;; Keywords: languages
 
 ;; This file is not part of GNU Emacs.
@@ -268,7 +268,7 @@ This function preserves point and mark."
 (defun fsharp-in-literal-p (&optional lim)
   "Return non-nil if point is in a Fsharp literal (a comment or
 string). The return value is specifically one of the symbols
-'comment or 'string. Optional argument LIM indicates the
+\\='comment or \\='string. Optional argument LIM indicates the
 beginning of the containing form, i.e. the limit on how far back
 to scan."
   ;; NOTE: Watch out for infinite recursion between this function and
@@ -285,8 +285,7 @@ to scan."
   "Returns non-nil if the current line should dedent one level."
   (save-excursion
     (progn (back-to-indentation)
-           (looking-at fsharp-outdent-re))
-    ))
+           (looking-at fsharp-outdent-re))))
 
 
 (defun fsharp--indenting-comment-p ()
@@ -459,8 +458,7 @@ comment."
             (goto-char here)
             (beginning-of-line)
             (delete-horizontal-space)
-            (indent-to (- indent outdent))
-            )))))
+            (indent-to (- indent outdent)))))))
 
 
 ;; Electric deletion
@@ -582,8 +580,7 @@ This function is normally bound to `indent-line-function' so
                          (delete-horizontal-space)
                          (indent-to need)))
                    (if move-to-indentation-p (back-to-indentation)))
-          (insert-tab)))
-      )))
+          (insert-tab))))))
 
 
 ;; NOTE[gastove|2019-10-25] An interesting point: this function is *only* ever
@@ -686,8 +683,7 @@ above, but only when the previous line is not itself a continuation line."
       ;; statement, add some extra offset.
       (+ (current-column) (if (fsharp-statement-opens-block-p)
                               fsharp-continuation-offset 0)
-         1)
-      )))
+         1))))
 
 
 (defun fsharp--compute-indentation-relative-to-previous (honor-block-close-p)
@@ -720,11 +716,7 @@ lines (if any)"
                                   (back-to-indentation)
                                   (and (not (looking-at prefix-re))
                                        (or (looking-at "[^/]")
-                                           (not (zerop (current-column)))
-                                           ))
-                                  ))
-                           ))
-            )))
+                                           (not (zerop (current-column))))))))))))
       ;; if we landed inside a string, go to the beginning of that
       ;; string. this handles triple quoted, multi-line spanning
       ;; strings.
@@ -742,8 +734,7 @@ lines (if any)"
              fsharp-indent-offset
            (if (and honor-block-close-p (fsharp-statement-closes-block-p))
                (- fsharp-indent-offset)
-             0)))))
-  )
+             0))))))
 
 
 (defun fsharp-newline-and-indent ()
@@ -775,6 +766,10 @@ dedenting."
            (open-bracket-pos (fsharp-nesting-level)))
 
       (cond
+       ((and open-bracket-pos (eq (and (looking-back "[[:space:]\n\r]+" nil t)
+				       (match-beginning 0))
+				  (1+ open-bracket-pos)))
+	fsharp-indent-offset)
        ;; Continuation Lines
        ((fsharp-continuation-line-p)
         (if open-bracket-pos
@@ -857,8 +852,7 @@ it's tried again going backward."
       (or noninteractive
           (message "%s value of fsharp-indent-offset set to %d"
                    (if global "Global" "Local")
-                   fsharp-indent-offset)))
-    ))
+                   fsharp-indent-offset)))))
 
 (defun fsharp-comment-indent-function ()
   "Fsharp version of `comment-indent-function'."
@@ -873,8 +867,7 @@ it's tried again going backward."
            (setq eol (match-beginning 0)))
       (goto-char eol)
       (skip-chars-backward " \t")
-      (max comment-column (+ (current-column) (if (bolp) 0 1)))
-      )))
+      (max comment-column (+ (current-column) (if (bolp) 0 1))))))
 
 (defun fsharp-narrow-to-defun (&optional class)
   "Make text outside current defun invisible.
@@ -1142,8 +1135,7 @@ To mark the current `def', see `\\[fsharp-mark-def-or-class]'."
         (start-of-stmt (goto-char (fsharp-point 'bos)))
         (start-re (cond ((eq class 'either) "^[ \t]*\\(type\\|let\\)\\>")
                         (class "^[ \t]*type\\>")
-                        (t "^[ \t]*let\\>")))
-        )
+                        (t "^[ \t]*let\\>"))))
     ;; searching backward
     (if (and (< 0 count)
              (or (/= start-of-stmt start-of-line)
@@ -1621,8 +1613,7 @@ moves to the end of the block (& does not set mark or display a msg)."
       (while (and
               (setq last-pos (point))   ; always true -- side effect
               (fsharp-goto-statement-below)
-              (> (current-indentation) initial-indent)
-              )))
+              (> (current-indentation) initial-indent))))
 
      ;; else plain code line; stop at next blank line, or stmt or
      ;; indenting comment line indented <
diff --git a/fsharp-mode-util.el b/fsharp-mode-util.el
index 416ddd3f..d20106a4 100644
--- a/fsharp-mode-util.el
+++ b/fsharp-mode-util.el
@@ -1,4 +1,4 @@
-;;; fsharp-mode-util.el --- utility functions
+;;; fsharp-mode-util.el --- utility functions -*- lexical-binding: t -*-
 
 ;; Copyright (C) 2015 Robin Neatherway
 
@@ -23,11 +23,10 @@
 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 ;; Boston, MA 02110-1301, USA.
 
-(with-no-warnings (require 'cl))
-(require 'dash)
+(require 'cl-lib)
 
 (defvar fsharp-ac-using-mono
-  (case system-type
+  (cl-case system-type
     ((windows-nt cygwin msdos) nil)
     (otherwise t))
   "Whether the .NET runtime in use is mono.
@@ -36,36 +35,39 @@ for all *nix.")
 
 (defun fsharp-mode--program-files-x86 ()
   (file-name-as-directory
-   (car (-drop-while 'not
-                     (list (getenv "ProgramFiles(x86)")
-                           (getenv "ProgramFiles")
-                           "C:\\Program Files (x86)")))))
+   (or (getenv "ProgramFiles(x86)")
+       (getenv "ProgramFiles")
+       "C:\\Program Files (x86)")))
 
 (defun fsharp-mode--vs2017-msbuild-find (exe)
   "Return EXE absolute path for Visual Studio 2017, if existent, else nil."
-  (->> (--map (concat (fsharp-mode--program-files-x86)
-                      "Microsoft Visual Studio/2017/"
-                      it
-                      "msbuild/15.0/bin/"
-                      exe)
-              '("Enterprise/" "Professional/" "Community/" "BuildTools/"))
-       (--first (file-executable-p it))))
+  (let ((candidates (mapcar (lambda (edition)
+                              (concat (fsharp-mode--program-files-x86)
+                                      edition
+                                      "msbuild/15.0/bin/"
+                                      exe))
+                            '("Enterprise/" "Professional/"
+                              "Community/" "BuildTools/"))))
+    (cl-find-if (lambda (exe) (file-executable-p exe)) candidates)))
 
 (defun fsharp-mode--msbuild-find (exe)
   (if fsharp-ac-using-mono
       (executable-find exe)
-    (let* ((searchdirs (--map (concat (fsharp-mode--program-files-x86)
-                                      "MSBuild/" it "/Bin")
-                              '("14.0" "13.0" "12.0")))
+    (let* ((searchdirs (mapcar (lambda (ver)
+                                 (concat (fsharp-mode--program-files-x86)
+                                         "MSBuild/" ver "/Bin"))
+                               '("14.0" "13.0" "12.0")))
            (exec-path (append searchdirs exec-path)))
       (or (fsharp-mode--vs2017-msbuild-find exe) (executable-find exe)))))
 
 (defun fsharp-mode--executable-find (exe)
   (if fsharp-ac-using-mono
       (executable-find exe)
-    (let* ((searchdirs (--map (concat (fsharp-mode--program-files-x86)
-                                      "Microsoft SDKs/F#/" it "/Framework/v4.0")
-                              '("10.1" "4.0" "3.1" "3.0")))
+    (let* ((searchdirs (mapcar (lambda (ver)
+                                 (concat (fsharp-mode--program-files-x86)
+                                         "Microsoft SDKs/F#/"
+                                         ver "/Framework/v4.0"))
+                               '("10.1" "4.0" "3.1" "3.0")))
            (exec-path (append searchdirs exec-path)))
       (executable-find exe))))
 
diff --git a/fsharp-mode.el b/fsharp-mode.el
index e2f00b4b..82bd5d86 100644
--- a/fsharp-mode.el
+++ b/fsharp-mode.el
@@ -5,11 +5,11 @@
 ;; Author: 1993-1997 Xavier Leroy, Jacques Garrigue and Ian T Zimmerman
 ;;         2010-2011 Laurent Le Brun <laurent@le-brun.eu>
 ;;         2012-2014 Robin Neatherway <robin.neatherway@gmail.com>
-;;         2017-2019 Jürgen Hötzel
+;;         2017-2023 Jürgen Hötzel
 ;; Maintainer: Jürgen Hötzel
-;; Package-Requires: ((emacs "25")  (s "1.3.1") (dash "1.1.0") (eglot))
+;; Package-Requires: ((emacs "25"))
 ;; Keywords: languages
-;; Version: 1.9.15
+;; Version: 1.11-snapshot
 
 ;; This file is not part of GNU Emacs.
 
@@ -35,7 +35,8 @@
 (require 'fsharp-mode-util)
 (require 'compile)
 (require 'project)
-(require 'dash)
+(require 'subr-x)
+(require 'seq)
 
 (defgroup fsharp nil
   "Support for the Fsharp programming language, <http://www.fsharp.net/>"
@@ -45,11 +46,11 @@
 ;;; Compilation
 
 (defvar fsharp-compile-command
-  (-any #'fsharp-mode--executable-find '("fsharpc" "fsc"))
+  (seq-some #'fsharp-mode--executable-find '("fsharpc" "fsc"))
   "The program used to compile F# source files.")
 
 (defvar fsharp-build-command
-  (-any #'fsharp-mode--msbuild-find '("msbuild" "xbuild"))
+  (seq-some #'fsharp-mode--msbuild-find '("msbuild" "xbuild"))
   "The command used to build F# projects and solutions.")
 
 ;;; ----------------------------------------------------------------------------
@@ -112,7 +113,9 @@
       (define-key map [eval-phrase] '("Eval phrase" . fsharp-eval-phrase)))))
 
 ;;;###autoload
-(add-to-list 'auto-mode-alist '("\\.fs[iylx]?\\'" . fsharp-mode))
+(progn
+  (add-to-list 'auto-mode-alist '("\\.fs[iylx]?\\'" . fsharp-mode))
+  (add-to-list 'auto-mode-alist '("\\.fsproj\\'" . nxml-mode)))
 
 (defvar fsharp-mode-syntax-table nil
   "Syntax table in use in fsharp mode buffers.")
@@ -170,6 +173,13 @@
 (defvar fsharp-mode-hook nil
   "Hook for fsharp-mode")
 
+(defcustom fsharp-autosave-on-file-load nil
+  "Determine if buffer should be automatically saved on
+`fsharp-load-buffer-file'.
+If set to t, the buffer will always be saved, silently."
+  :type 'boolean
+  :group 'fsharp-mode)
+
 ;;;###autoload
 (define-derived-mode fsharp-mode prog-mode "fsharp"
   :syntax-table fsharp-mode-syntax-table
@@ -193,18 +203,14 @@
           comment-column
           comment-start-skip
           comment-indent-function
+          adaptive-fill-regexp
           parse-sexp-ignore-comments
           indent-region-function
           indent-line-function
           add-log-current-defun-function
           underline-minimum-offset
           compile-command
-          syntax-propertize-function
-          company-backends
-          company-auto-complete
-          company-auto-complete-chars
-          company-require-match
-          company-tooltip-align-annotations))
+          syntax-propertize-function))
 
   (setq local-abbrev-table       fsharp-mode-abbrev-table
         paragraph-start          (concat "^$\\|" page-delimiter)
@@ -215,6 +221,7 @@
         comment-end              ""
         comment-column           40
         comment-start-skip       "///* *"
+        adaptive-fill-regexp     "[ \t]*\\(//+[ \t]*\\)*"
         comment-indent-function  'fsharp-comment-indent-function
         indent-region-function   'fsharp-indent-region
         indent-line-function     'fsharp-indent-line
@@ -234,11 +241,8 @@
   ;; has no deterministic indentation.
   (when (boundp 'electric-indent-inhibit) (setq electric-indent-inhibit t))
 
-  (let ((file (buffer-file-name)))
-    (when file
-      (setq compile-command (fsharp-mode-choose-compile-command file))))
-
-  (run-hooks 'fsharp-mode-hook))
+  (when-let ((file (buffer-file-name)))
+    (setq compile-command (fsharp-mode-choose-compile-command file))))
 
 (defun fsharp-mode-choose-compile-command (file)
   "Format an appropriate compilation command, depending on several factors:
@@ -294,10 +298,11 @@
   (require 'inf-fsharp-mode)
   (let* ((name buffer-file-name)
          (command (concat "#load \"" name "\"")))
-    (when (buffer-modified-p)
-      (when (y-or-n-p (concat "Do you want to save \"" name "\" before
-loading it? "))
-        (save-buffer)))
+    (when (and (buffer-modified-p)
+	       (or fsharp-autosave-on-file-load
+		   (y-or-n-p (concat "Do you want to save \"" name
+				     "\" before loading it? "))))
+      (save-buffer))
     (fsharp-run-process-if-needed)
     (fsharp-simple-send inferior-fsharp-buffer-name command)))
 
@@ -341,15 +346,7 @@ whole string."
 (defun fsharp-mode/find-sln-or-fsproj (dir-or-file)
   "Search for a solution or F# project file in any enclosing
 folders relative to DIR-OR-FILE."
-  (or (fsharp-mode/find-sln dir-or-file)
-      (fsharp-mode/find-fsproj dir-or-file)))
-
-(defun fsharp-mode/find-sln (dir-or-file)
-  (fsharp-mode-search-upwards (rx (0+ nonl) ".sln" eol)
-                              (file-name-directory dir-or-file)))
-
-(defun fsharp-mode/find-fsproj (dir-or-file)
-  (fsharp-mode-search-upwards (rx (0+ nonl) ".fsproj" eol)
+  (fsharp-mode-search-upwards (rx (0+ nonl) (or ".fsproj" ".sln") eol)
                               (file-name-directory dir-or-file)))
 
 (defun fsharp-mode-search-upwards (regex dir)
@@ -364,7 +361,7 @@ folders relative to DIR-OR-FILE."
 
 ;; Make project.el aware of fsharp projects
 (defun fsharp-mode-project-root (dir)
-  (-when-let (project-file (fsharp-mode/find-sln-or-fsproj dir))
+  (when-let (project-file (fsharp-mode/find-sln-or-fsproj dir))
     (cons 'fsharp (file-name-directory project-file))))
 
 (cl-defmethod project-roots ((project (head fsharp)))
diff --git a/inf-fsharp-mode.el b/inf-fsharp-mode.el
index 15e821d8..fbfb05db 100644
--- a/inf-fsharp-mode.el
+++ b/inf-fsharp-mode.el
@@ -28,7 +28,7 @@
 (require 'comint)
 (require 'fsharp-mode-util)
 
-(with-no-warnings (require 'cl))
+(require 'cl-lib)
 
 ;; User modifiable variables
 
@@ -38,10 +38,11 @@
   "*If true, display the inferior fsharp buffer when evaluating expressions.")
 
 (defvar inferior-fsharp-program
-  (if fsharp-ac-using-mono
-      "fsharpi --readline-"
-    (concat "\"" (fsharp-mode--executable-find "fsi.exe") "\" --fsi-server-input-codepage:65001"))
-  "*Program name for invoking an inferior fsharp from Emacs.")
+  (cond
+   ((executable-find "dotnet") "dotnet fsi --readline-")
+   (fsharp-ac-using-mono "fsharpi --readline-")
+   (t (concat "\"" (fsharp-mode--executable-find "fsi.exe") "\" --fsi-server-input-codepage:65001")))
+  "Inferior F# command.")
 
 ;; End of User modifiable variables
 
@@ -72,13 +73,13 @@ be sent from another buffer in fsharp mode.
   (set (make-local-variable 'comment-column) 40)
   (set (make-local-variable 'comment-start-skip) "(\\*+ *")
   (set (make-local-variable 'parse-sexp-ignore-comments) nil)
-  (set (make-local-variable 'comint-process-echoes) nil)
+  (set (make-local-variable 'comint-process-echoes) t)
   (run-hooks 'inferior-fsharp-mode-hooks)
 
   ;; use compilation mode to parse errors, but RET and C-cC-c should still be from comint-mode
   (compilation-minor-mode)
   (make-local-variable 'minor-mode-map-alist)
-  (setq minor-mode-map-alist (assq-delete-all 'compilation-minor-mode (copy-seq minor-mode-map-alist))))
+  (setq minor-mode-map-alist (assq-delete-all 'compilation-minor-mode (cl-copy-seq minor-mode-map-alist))))
 
 (defconst inferior-fsharp-buffer-subname "inferior-fsharp")
 (defconst inferior-fsharp-buffer-name
@@ -99,7 +100,7 @@ If FILE is not a Tramp filename return FILENAME"
           (or cmd (read-from-minibuffer "fsharp toplevel to run: "
                                         inferior-fsharp-program)))
     (let ((cmdlist (inferior-fsharp-args-to-list inferior-fsharp-program))
-          (process-connection-type nil))
+          (process-connection-type 'pty))
       (with-current-buffer (apply (function make-comint)
                                   inferior-fsharp-buffer-subname
                                   (car cmdlist) nil
@@ -146,9 +147,7 @@ Input and output via buffer `*inferior-fsharp*'."
     (while
         (> count 0)
       (previous-multiframe-window)
-      (setq count (- count 1)))
-    )
-  )
+      (setq count (- count 1)))))
 
 (defun inferior-fsharp-eval-region (start end)
   "Send the current region to the inferior fsharp process."
diff --git a/test/Test1/Pervasive.fs b/test/Test1/Pervasive.fs
new file mode 100644
index 00000000..4fb011c5
--- /dev/null
+++ b/test/Test1/Pervasive.fs
@@ -0,0 +1,3 @@
+let printtest args =
+    printfn "Hello %d" 10
+    0
diff --git a/test/Test1/Test1.fsproj b/test/Test1/Test1.fsproj
index 348b5cba..5cccab99 100644
--- a/test/Test1/Test1.fsproj
+++ b/test/Test1/Test1.fsproj
@@ -2,13 +2,14 @@
 
   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFramework>netcoreapp2.1</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
   </PropertyGroup>
 
   <ItemGroup>
     <Compile Include="Error.fs" />
     <Compile Include="FileTwo.fs" />
     <Compile Include="Program.fs" />
+    <Compile Include="Pervasive.fs" />
   </ItemGroup>
 
 </Project>
diff --git a/test/eglot-fsharp-integration-util.el b/test/eglot-fsharp-integration-util.el
new file mode 100644
index 00000000..c1fbf838
--- /dev/null
+++ b/test/eglot-fsharp-integration-util.el
@@ -0,0 +1,164 @@
+;;; eglot-fsharp-integration-util.el --- Helper for eglot integration tests  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022-2023  Jürgen Hötzel
+
+;; Author: Jürgen Hötzel <juergen@hoetzel.info>
+;; Keywords: processes
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; 
+
+;;; Code:
+(require 'edebug)
+
+(cl-defmacro eglot-fsharp--with-timeout (timeout &body body)
+  (declare (indent 1) (debug t))
+  `(eglot-fsharp--call-with-timeout ,timeout (lambda () ,@body)))
+
+(defun eglot-fsharp--call-with-timeout (timeout fn)
+  (let* ((tag (gensym "eglot-test-timeout"))
+         (timed-out (make-symbol "timeout"))
+         (timeout-and-message
+          (if (listp timeout) timeout
+            (list timeout "waiting for test to finish")))
+         (timeout (car timeout-and-message))
+         (message (cadr timeout-and-message))
+         (timer)
+         (retval))
+    (unwind-protect
+        (setq retval
+              (catch tag
+                (setq timer
+                      (run-with-timer timeout nil
+                                      (lambda ()
+                                        (unless edebug-active
+                                          (throw tag timed-out)))))
+                (funcall fn)))
+      (cancel-timer timer)
+      (when (eq retval timed-out)
+        (warn "Received Events for %s : %s"
+              (file-name-nondirectory (buffer-file-name))
+              (with-current-buffer (jsonrpc-events-buffer (eglot-current-server)) (buffer-string)))
+        (error "%s" (concat "Timed out " message))))))
+
+
+(defun eglot-fsharp--find-file-noselect (file &optional noerror)
+  (unless (or noerror
+              (file-readable-p file)) (error "%s does not exist" file))
+  (find-file-noselect file))
+
+(defun eglot-fsharp--tests-connect (&optional timeout)
+  (let* ((timeout (or timeout 10))
+         (eglot-sync-connect t)
+         (eglot-connect-timeout timeout))
+    (apply #'eglot--connect (eglot--guess-contact))))
+
+(cl-defmacro eglot-fsharp--wait-for ((events-sym &optional (timeout 1) message) args &body body)
+  "Spin until FN match in EVENTS-SYM, flush events after it.
+Pass TIMEOUT to `eglot--with-timeout'."
+  (declare (indent 2) (debug (sexp sexp sexp &rest form)))
+  `(eglot-fsharp--with-timeout '(,timeout ,(or message
+                                        (format "waiting for:\n%s" (pp-to-string body))))
+     (let ((event
+            (cl-loop thereis (cl-loop for json in ,events-sym
+                                      for method = (plist-get json :method)
+                                      when (keywordp method)
+                                      do (plist-put json :method
+                                                    (substring
+                                                     (symbol-name method)
+                                                     1))
+                                      when (funcall
+                                            (jsonrpc-lambda ,args ,@body) json)
+                                      return (cons json before)
+                                      collect json into before)
+                     for i from 0
+                     when (zerop (mod i 5))
+                     ;; do (eglot--message "still struggling to find in %s"
+                     ;;                    ,events-sym)
+                     do
+                     ;; `read-event' is essential to have the file
+                     ;; watchers come through.
+                     (read-event "[eglot] Waiting a bit..." nil 0.1)
+                     (accept-process-output nil 0.1))))
+       (setq ,events-sym (cdr event))
+       (eglot--message "Event detected:\n%s"
+                       (pp-to-string (car event))))))
+
+
+(cl-defmacro eglot-fsharp--sniffing ((&key server-requests
+                                    server-notifications
+                                    server-replies
+                                    client-requests
+                                    client-notifications
+                                    client-replies)
+                              &rest body)
+  "Run BODY saving LSP JSON messages in variables, most recent first."
+  (declare (indent 1) (debug (sexp &rest form)))
+  (let ((log-event-ad-sym (make-symbol "eglot-fsharp--event-sniff")))
+    `(unwind-protect
+         (let ,(delq nil (list server-requests
+                               server-notifications
+                               server-replies
+                               client-requests
+                               client-notifications
+                               client-replies))
+           (advice-add
+            #'jsonrpc--log-event :before
+            (lambda (_proc message &optional type)
+              (cl-destructuring-bind (&key method id _error &allow-other-keys)
+                  message
+                (let ((req-p (and method id))
+                      (notif-p method)
+                      (reply-p id))
+                  (cond
+                   ((eq type 'server)
+                    (cond (req-p ,(when server-requests
+                                    `(push message ,server-requests)))
+                          (notif-p ,(when server-notifications
+                                      `(push message ,server-notifications)))
+                          (reply-p ,(when server-replies
+                                      `(push message ,server-replies)))))
+                   ((eq type 'client)
+                    (cond (req-p ,(when client-requests
+                                    `(push message ,client-requests)))
+                          (notif-p ,(when client-notifications
+                                      `(push message ,client-notifications)))
+                          (reply-p ,(when client-replies
+                                      `(push message ,client-replies)))))))))
+            '((name . ,log-event-ad-sym)))
+           ,@body)
+       (advice-remove #'jsonrpc--log-event ',log-event-ad-sym))))
+
+
+
+(defun eglot-fsharp--sniff-diagnostics (file-name-suffix)
+  (eglot-fsharp--sniffing (:server-notifications s-notifs)
+                          (eglot-fsharp--wait-for (s-notifs 20)
+                                           (&key _id method params &allow-other-keys)
+                                           (and
+                                            (string= method "textDocument/publishDiagnostics")
+                                            (string-suffix-p file-name-suffix (plist-get params :uri))))))
+
+(defun eglot-fsharp--sniff-method (method-name)
+  (eglot-fsharp--sniffing (:server-notifications s-notifs)
+                          (eglot-fsharp--wait-for (s-notifs 20)
+                                           (&key _id method params &allow-other-keys)
+                                           (and
+                                            (string= method method-name)))))
+
+(provide 'eglot-fsharp-integration-util)
+;;; integration-util.el ends here
diff --git a/test/expression.fsx b/test/expression.fsx
new file mode 100644
index 00000000..0bcc1671
--- /dev/null
+++ b/test/expression.fsx
@@ -0,0 +1 @@
+1 + 1;;
diff --git a/test/fsharp-mode-font-tests.el b/test/fsharp-mode-font-tests.el
new file mode 100644
index 00000000..55eb423f
--- /dev/null
+++ b/test/fsharp-mode-font-tests.el
@@ -0,0 +1,42 @@
+;;; fsharp-mode-font-tests.el ---                         -*- lexical-binding: t; -*-
+
+(require 'buttercup)
+(require 'fsharp-mode)
+
+(defmacro with-highlighted (src &rest body)
+  "Insert SRC in a temporary fsharp-mode buffer, apply syntax highlighting,
+then run BODY."
+  `(with-temp-buffer
+     (fsharp-mode)
+     (insert ,src)
+     (goto-char (point-min))
+     ;; Ensure we've syntax-highlighted the whole buffer.
+     (if (fboundp 'font-lock-ensure)
+         (font-lock-ensure)
+       (with-no-warnings
+         (font-lock-fontify-buffer)))
+     ,@body))
+
+(defun str-face (op)
+  (goto-char (point-min))
+  (search-forward op)
+  (left-char 2)
+  (face-at-point))
+
+(describe "When locking operators"
+          (it "uses ui operator face for pipes"
+              (with-highlighted "<<| |>> |> ||> |||> <| <|| <||| <|> <<|!"
+                                (should (equal (str-face " |> ") 'fsharp-ui-operator-face))
+                                (should (equal (str-face " ||> ") 'fsharp-ui-operator-face))
+                                (should (equal (str-face " |||> ") 'fsharp-ui-operator-face))
+                                (should (equal (str-face " <| ") 'fsharp-ui-operator-face))
+                                (should (equal (str-face " <|| ") 'fsharp-ui-operator-face))
+                                (should (equal (str-face " <||| ") 'fsharp-ui-operator-face)))))
+
+(describe "When locking operators"
+          (it "uses ui generic face for custom operators containing pipes"
+              (with-highlighted "<<| |>> |> ||> |||> <| <|| <||| <|> <<|!"
+                                (should (equal (str-face "<<| ") 'fsharp-ui-generic-face))
+                                (should (equal (str-face " |>> ") 'fsharp-ui-generic-face))
+                                (should (equal (str-face " <|> ") 'fsharp-ui-generic-face))
+                                (should (equal (str-face " <<|!") 'fsharp-ui-generic-face)))))
diff --git a/test/fsharp-mode-structure-tests.el b/test/fsharp-mode-structure-tests.el
index a5b9da1b..7792b383 100644
--- a/test/fsharp-mode-structure-tests.el
+++ b/test/fsharp-mode-structure-tests.el
@@ -53,46 +53,46 @@
 ;;-------------------------------- Predicates --------------------------------;;
 
 (describe "The `fsharp-backslash-continuation-line-p' predicate"
-  (it "returns true when we expect it to"
-    (let ((file (file-truename (concat fsharp-struct-test-files-dir "ContinuationLines.fs"))))
-      (with-current-buffer (find-file-noselect file)
-	(beginning-of-buffer)
-	(should (eq (fsharp--hanging-operator-continuation-line-p) nil))
-	(forward-line 1)
-	(should (eq (fsharp--hanging-operator-continuation-line-p) nil))
-	(forward-line 5)
-	(should (eq (fsharp--hanging-operator-continuation-line-p) t))))))
+          (it "returns true when we expect it to"
+              (let ((file (file-truename (concat fsharp-struct-test-files-dir "ContinuationLines.fs"))))
+                (with-current-buffer (find-file-noselect file)
+	          (beginning-of-buffer)
+	          (should (eq (fsharp--hanging-operator-continuation-line-p) nil))
+	          (forward-line 1)
+	          (should (eq (fsharp--hanging-operator-continuation-line-p) nil))
+	          (forward-line 5)
+	          (should (eq (fsharp--hanging-operator-continuation-line-p) t))))))
 
 (describe "The `fsharp-in-literal-p'"
-  (it "return non-nil in both strings and comments?"
-    (let ((literals-file (file-truename (concat fsharp-struct-test-files-dir "Literals.fs"))))
-      (with-current-buffer (find-file-noselect  literals-file)
-	;; Comments
-	(goto-char 3)
-	(should (eq (fsharp-in-literal-p) 'comment))
-	(goto-char 642)
-	(should (eq (fsharp-in-literal-p) 'comment))
-	(goto-char 968)
-	(should (eq (fsharp-in-literal-p) 'comment))
-	(goto-char 1481)
-	(should (eq (fsharp-in-literal-p) 'comment))
-	(goto-char 2124)
-	(should (eq (fsharp-in-literal-p) 'comment))
-	;; String literals
-	(goto-char 2717)
-	(should (eq (fsharp-in-literal-p) 'string))
-	;; This string contains an inner, backslash-escaped string.
-	;; First, with point outside the backslash-escaped string:
-	(goto-char 2759)
-	(should (eq (fsharp-in-literal-p) 'string))
-	;; ...and now with point inside it
-	(goto-char 2774)
-	(should (eq (fsharp-in-literal-p) 'string))
-	;; Inside triple-quoted strings
-	(goto-char 2835)
-	(should (eq (fsharp-in-literal-p) 'string))
-	(goto-char 2900)
-	(should (eq (fsharp-in-literal-p) 'string))))))
+          (it "return non-nil in both strings and comments?"
+              (let ((literals-file (file-truename (concat fsharp-struct-test-files-dir "Literals.fs"))))
+                (with-current-buffer (find-file-noselect  literals-file)
+	          ;; Comments
+	          (goto-char 3)
+	          (should (eq (fsharp-in-literal-p) 'comment))
+	          (goto-char 642)
+	          (should (eq (fsharp-in-literal-p) 'comment))
+	          (goto-char 968)
+	          (should (eq (fsharp-in-literal-p) 'comment))
+	          (goto-char 1481)
+	          (should (eq (fsharp-in-literal-p) 'comment))
+	          (goto-char 2124)
+	          (should (eq (fsharp-in-literal-p) 'comment))
+	          ;; String literals
+	          (goto-char 2717)
+	          (should (eq (fsharp-in-literal-p) 'string))
+	          ;; This string contains an inner, backslash-escaped string.
+	          ;; First, with point outside the backslash-escaped string:
+	          (goto-char 2759)
+	          (should (eq (fsharp-in-literal-p) 'string))
+	          ;; ...and now with point inside it
+	          (goto-char 2774)
+	          (should (eq (fsharp-in-literal-p) 'string))
+	          ;; Inside triple-quoted strings
+	          (goto-char 2835)
+	          (should (eq (fsharp-in-literal-p) 'string))
+	          (goto-char 2900)
+	          (should (eq (fsharp-in-literal-p) 'string))))))
 
 ;; NOTE[gastove|2019-10-31] I am entirely convinced this doesn't work precisely
 ;; as it should, because it depends on `fsharp-goto-beyond-final-line', which I
@@ -113,161 +113,169 @@
 ;;--------------------- Nesting and Indentation Functions ---------------------;;
 
 (describe "The `fsharp-nesting-level' function"
-  (it "returns nil when we expect it to"
-    (with-temp-buffer
-      (insert "let x = 5")
-      (end-of-buffer)
-      (should (eq (fsharp-nesting-level) nil)))))
+          (it "returns nil when we expect it to"
+              (with-temp-buffer
+                (insert "let x = 5")
+                (end-of-buffer)
+                (should (eq (fsharp-nesting-level) nil)))))
 
 (describe "The `fsharp-nesting-level' function"
-  :var ((file (file-truename (concat fsharp-struct-test-files-dir "Nesting.fs"))))
-  (it  "correctly return the point position of the opening pair closest to point"
-    ;; The character positions use here reference characters noted in comments in Nesting.fs
-    ;; Test a normal list
-    (with-current-buffer (find-file-noselect file)
-      (goto-char 645)
-      (should (eq (fsharp-nesting-level) 640)))
-
-    ;; Get the opening bracket of an inner list from a single-line nested list
-    (with-current-buffer (find-file-noselect file)
-      (goto-char 717)
-      (should (eq (fsharp-nesting-level) 706)))
-
-    ;; Opening bracket for a multi-line non-nested list
-    (with-current-buffer (find-file-noselect file)
-      (goto-char 795)
-      (should (eq (fsharp-nesting-level) 777)))
-
-    ;; Inner most opening bracket for a multi-line multi-nested list
-    (with-current-buffer (find-file-noselect file)
-      (goto-char 960)
-      (should (eq (fsharp-nesting-level) 955)))
-    ;; Middle opening bracket for same list as previous
-    (with-current-buffer (find-file-noselect file)
-      (goto-char 954)
-      (should (eq (fsharp-nesting-level) 953)))
-    (with-current-buffer (find-file-noselect file)
-      (goto-char 974)
-      (should (eq (fsharp-nesting-level) 953)))
-    ;; Outermost opening bracket for same list
-    (with-current-buffer (find-file-noselect file)
-      (goto-char 977)
-      (should (eq (fsharp-nesting-level) 947)))
-
-    ;; Basic Async form, should return the opening {
-    (with-current-buffer (find-file-noselect file)
-      (goto-char 1088)
-      (should (eq (fsharp-nesting-level) 1060)))
-    ;; Same async form, inner async call
-    (with-current-buffer (find-file-noselect file)
-      (goto-char 1129)
-      (should (eq (fsharp-nesting-level) 1121)))
-
-    ;; Lambda, wrapped in parens, should return the opening (
-    (with-current-buffer (find-file-noselect file)
-      (goto-char 1238)
-      (should (eq (fsharp-nesting-level) 1208)))))
+          :var ((file (file-truename (concat fsharp-struct-test-files-dir "Nesting.fs"))))
+          (it  "correctly return the point position of the opening pair closest to point"
+               ;; The character positions use here reference characters noted in comments in Nesting.fs
+               ;; Test a normal list
+               (with-current-buffer (find-file-noselect file)
+                 (goto-char 645)
+                 (should (eq (fsharp-nesting-level) 640)))
+
+               ;; Get the opening bracket of an inner list from a single-line nested list
+               (with-current-buffer (find-file-noselect file)
+                 (goto-char 717)
+                 (should (eq (fsharp-nesting-level) 706)))
+
+               ;; Opening bracket for a multi-line non-nested list
+               (with-current-buffer (find-file-noselect file)
+                 (goto-char 795)
+                 (should (eq (fsharp-nesting-level) 777)))
+
+               ;; Inner most opening bracket for a multi-line multi-nested list
+               (with-current-buffer (find-file-noselect file)
+                 (goto-char 960)
+                 (should (eq (fsharp-nesting-level) 955)))
+               ;; Middle opening bracket for same list as previous
+               (with-current-buffer (find-file-noselect file)
+                 (goto-char 954)
+                 (should (eq (fsharp-nesting-level) 953)))
+               (with-current-buffer (find-file-noselect file)
+                 (goto-char 974)
+                 (should (eq (fsharp-nesting-level) 953)))
+               ;; Outermost opening bracket for same list
+               (with-current-buffer (find-file-noselect file)
+                 (goto-char 977)
+                 (should (eq (fsharp-nesting-level) 947)))
+
+               ;; Basic Async form, should return the opening {
+               (with-current-buffer (find-file-noselect file)
+                 (goto-char 1088)
+                 (should (eq (fsharp-nesting-level) 1060)))
+               ;; Same async form, inner async call
+               (with-current-buffer (find-file-noselect file)
+                 (goto-char 1129)
+                 (should (eq (fsharp-nesting-level) 1121)))
+
+               ;; Lambda, wrapped in parens, should return the opening (
+               (with-current-buffer (find-file-noselect file)
+                 (goto-char 1238)
+                 (should (eq (fsharp-nesting-level) 1208)))))
 
 
 (describe "The `fsharp--compute-indentaiton-open-bracket'"
-  :var ((file (file-truename (concat fsharp-struct-test-files-dir "BracketIndent.fs"))))
-  (it "returns the correct indentation in a variety of cases"
-    (with-current-buffer (find-file-noselect file)
-      ;; Opening bracket on same line as let, elements on same line; test element
-      (goto-char 44)
-      (let* ((nesting-level (fsharp-nesting-level))
-	     (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level)))
-	;; The value we expect
-	(should (eq indent-at-point 18))
-	;; Both entrypoints should have the same answer
-	(should (eq indent-at-point (fsharp-compute-indentation t))))
-
-      ;; Opening bracket on same line as let, elements on same line; test newline
-      (goto-char 81)
-      (let* ((nesting-level (fsharp-nesting-level))
-	     (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level)))
-	;; The value we expect
-	(should (eq indent-at-point 18))
-	;; Both entrypoints should have the same answer
-	(should (eq indent-at-point (fsharp-compute-indentation t))))
-
-      ;; Opening bracket on same line as let, elements on new line; test element
-      (goto-char 148)
-      (let* ((nesting-level (fsharp-nesting-level))
-	     (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level)))
-	(should (eq indent-at-point 4))
-	(should (eq indent-at-point (fsharp-compute-indentation t))))
-
-      ;; Opening bracket on same line as let, elements on new line; test newline
-      (goto-char 155)
-      (let* ((nesting-level (fsharp-nesting-level))
-	     (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level)))
-	(should (eq indent-at-point 4))
-	(should (eq indent-at-point (fsharp-compute-indentation t))))
-
-      ;; Opening bracket on own line; test element
-      (goto-char 231)
-      (let* ((nesting-level (fsharp-nesting-level))
-	     (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level)))
-	(should (eq indent-at-point 6))
-	(should (eq indent-at-point (fsharp-compute-indentation t))))
-
-      ;; Opening bracket on own line; test newline
-      (goto-char 236)
-      (let* ((nesting-level (fsharp-nesting-level))
-	     (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level)))
-	(should (eq indent-at-point 6))
-	(should (eq indent-at-point (fsharp-compute-indentation t)))))))
+          :var ((file (file-truename (concat fsharp-struct-test-files-dir "BracketIndent.fs"))))
+          (it "returns the correct indentation in a variety of cases"
+              (with-current-buffer (find-file-noselect file)
+                ;; Opening bracket on same line as let, elements on same line; test element
+                (goto-char 44)
+                (let* ((nesting-level (fsharp-nesting-level))
+	               (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level)))
+	          ;; The value we expect
+	          (should (eq indent-at-point 18))
+	          ;; Both entrypoints should have the same answer
+	          (should (eq indent-at-point (fsharp-compute-indentation t))))
+
+                ;; Opening bracket on same line as let, elements on same line; test newline
+                (goto-char 81)
+                (let* ((nesting-level (fsharp-nesting-level))
+	               (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level)))
+	          ;; The value we expect
+	          (should (eq indent-at-point 18))
+	          ;; Both entrypoints should have the same answer
+	          (should (eq indent-at-point (fsharp-compute-indentation t))))
+
+                ;; Opening bracket on same line as let, elements on new line; test element
+                (goto-char 148)
+                (let* ((nesting-level (fsharp-nesting-level))
+	               (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level)))
+	          (should (eq indent-at-point 4))
+	          (should (eq indent-at-point (fsharp-compute-indentation t))))
+
+                ;; Opening bracket on same line as let, elements on new line; test newline
+                (goto-char 155)
+                (let* ((nesting-level (fsharp-nesting-level))
+	               (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level)))
+	          (should (eq indent-at-point 4))
+	          (should (eq indent-at-point (fsharp-compute-indentation t))))
+
+                ;; Opening bracket on own line; test element
+                (goto-char 231)
+                (let* ((nesting-level (fsharp-nesting-level))
+	               (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level)))
+	          (should (eq indent-at-point 6))
+	          (should (eq indent-at-point (fsharp-compute-indentation t))))
+
+                ;; Opening bracket on own line; test newline
+                (goto-char 236)
+                (let* ((nesting-level (fsharp-nesting-level))
+	               (indent-at-point (fsharp--compute-indentation-open-bracket nesting-level)))
+	          (should (eq indent-at-point 6))
+	          (should (eq indent-at-point (fsharp-compute-indentation t)))))))
 
 
 (describe "The `fsharp--compute-indentation-continuation-line' function"
-  :var ((continuation-line "let x = 5 +"))
-  (it "indents correctly"
-    (with-temp-buffer
-      (fsharp-mode)
-      (insert continuation-line)
-      (fsharp-newline-and-indent)
-      (should (eq (fsharp--compute-indentation-continuation-line) 8))
-      (should (eq (fsharp--compute-indentation-continuation-line) (fsharp-compute-indentation t))))))
+          :var ((continuation-line "let x = 5 +"))
+          (it "indents correctly"
+              (with-temp-buffer
+                (fsharp-mode)
+                (insert continuation-line)
+                (fsharp-newline-and-indent)
+                (should (eq (fsharp--compute-indentation-continuation-line) 8))
+                (should (eq (fsharp--compute-indentation-continuation-line) (fsharp-compute-indentation t))))))
 
 
 (describe "The `fsharp-compute-indentation-relative-to-previous' function'"
-  :var ((file (concat fsharp-struct-test-files-dir "Relative.fs")))
-  (it "indents correctly releative to previous line"
-    ;; Discriminated unions
-    (with-current-buffer (find-file-noselect file)
-      (goto-char 57)
-      (should (eq (fsharp--compute-indentation-relative-to-previous t) 4))
-      (should (eq (fsharp--compute-indentation-relative-to-previous t)
-		  (fsharp-compute-indentation t)))
-
-      ;; If/Else blocks
-      ;; if an if then are on the same line, the next line is indented
-      (goto-char 96)
-      (should (eq (fsharp--compute-indentation-relative-to-previous t) 4))
-      (should (eq (fsharp--compute-indentation-relative-to-previous t)
-		  (fsharp-compute-indentation t)))
-
-      ;; An else is not indented further; *however*, the indentation relative to
-      ;; previous will be 4, but `fsharp-compute-indentation' will return 0
-      ;; because the previous line is not a continuation line.
-      ;;
-      ;; However! This test case doesn't currently work. Indentation code
-      ;; produces indent of 0, but the compute indentation functions proudce an
-      ;; indent of 4, which is wrong.
-      ;;
-      ;; (goto-char 124)
-      ;; (should (eq (fsharp--compute-indentation-relative-to-previous t) 4))
-      ;; (should-not (eq (fsharp--compute-indentation-relative-to-previous t)
-      ;;                 (fsharp-compute-indentation t)))
-
-      ;; when a then is on its own line, the next line is indented
-      (goto-char 154)
-      (should (eq (fsharp--compute-indentation-relative-to-previous t) 4))
-      (should (eq (fsharp--compute-indentation-relative-to-previous t)
-		  (fsharp-compute-indentation t)))
-      ;; likewise an else
-      (goto-char 180)
-      (should (eq (fsharp--compute-indentation-relative-to-previous t) 4))
-      (should (eq (fsharp--compute-indentation-relative-to-previous t)
-		  (fsharp-compute-indentation t))))))
+          :var ((file (concat fsharp-struct-test-files-dir "Relative.fs")))
+          (it "indents correctly releative to previous line"
+              ;; Discriminated unions
+              (with-current-buffer (find-file-noselect file)
+                (goto-char 57)
+                (should (eq (fsharp--compute-indentation-relative-to-previous t) 4))
+                (should (eq (fsharp--compute-indentation-relative-to-previous t)
+		            (fsharp-compute-indentation t)))
+
+                ;; If/Else blocks
+                ;; if an if then are on the same line, the next line is indented
+                (goto-char 96)
+                (should (eq (fsharp--compute-indentation-relative-to-previous t) 4))
+                (should (eq (fsharp--compute-indentation-relative-to-previous t)
+		            (fsharp-compute-indentation t)))
+
+                ;; An else is not indented further; *however*, the indentation relative to
+                ;; previous will be 4, but `fsharp-compute-indentation' will return 0
+                ;; because the previous line is not a continuation line.
+                ;;
+                ;; However! This test case doesn't currently work. Indentation code
+                ;; produces indent of 0, but the compute indentation functions proudce an
+                ;; indent of 4, which is wrong.
+                ;;
+                ;; (goto-char 124)
+                ;; (should (eq (fsharp--compute-indentation-relative-to-previous t) 4))
+                ;; (should-not (eq (fsharp--compute-indentation-relative-to-previous t)
+                ;;                 (fsharp-compute-indentation t)))
+
+                ;; when a then is on its own line, the next line is indented
+                (goto-char 154)
+                (should (eq (fsharp--compute-indentation-relative-to-previous t) 4))
+                (should (eq (fsharp--compute-indentation-relative-to-previous t)
+		            (fsharp-compute-indentation t)))
+                ;; likewise an else
+                (goto-char 180)
+                (should (eq (fsharp--compute-indentation-relative-to-previous t) 4))
+                (should (eq (fsharp--compute-indentation-relative-to-previous t)
+		            (fsharp-compute-indentation t))))))
+
+(describe "The `fsharp-compute-indentation'"
+          :var ((file (concat fsharp-struct-test-files-dir "BracketIndent.fs")))
+          (it "indents on the first line after opening bracket"
+              (with-current-buffer (find-file-noselect file)
+                (goto-char (point-min))
+                (search-forward-regexp "let formatTwo = \\[\n")
+                (should (eq (fsharp-compute-indentation t) fsharp-indent-offset)))))
diff --git a/test/fsi-tests.el b/test/fsi-tests.el
new file mode 100644
index 00000000..4b22d186
--- /dev/null
+++ b/test/fsi-tests.el
@@ -0,0 +1,64 @@
+;;; fsi-tests.el --- Tests for F# interactive        -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2022-2023  Jürgen Hötzel
+
+;; Author: Jürgen Hötzel <juergen@hoetzel.info>
+;; Keywords: processes
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; 
+
+;;; Code:
+
+(load "project")                        ;Emacs 27 workaround: https://github.com/joaotavora/eglot/issues/549
+(require 'buttercup)
+(require 'fsharp-mode)
+
+(defun fsi-tests-wait-for-regex (timeout regexp)
+  (let ((start-time (float-time)))
+    (while (and (< (- (float-time) start-time) timeout)
+                (not (progn (goto-char (point-min)) (search-forward-regexp regexp nil t))))
+      (if (accept-process-output (get-buffer-process (current-buffer)) 0.2)
+          (message "[FSI Interactive] received output...")
+        (message "[FSI Interactive] waiting for output...")))))
+
+
+(describe "F# interactive"
+  :before-all (run-fsharp inferior-fsharp-program)
+  :before-each (with-current-buffer (get-buffer inferior-fsharp-buffer-name)
+                 (comint-clear-buffer))
+  (it "can eval expressions"
+    (with-current-buffer (find-file-noselect "test/expression.fsx")
+      (fsharp-eval-region (point-min) (point-max))
+      (with-current-buffer (get-buffer inferior-fsharp-buffer-name)
+        (fsi-tests-wait-for-regex 25 "it: int = 2$")
+        (let ((result (match-string-no-properties 0)))
+          (expect result :to-equal "it: int = 2")))))
+  (it "can load nuget references"
+    (let ((timeout 50)
+          (fsx-file "test/nuget.fsx"))
+      (with-current-buffer (find-file-noselect fsx-file)
+        (fsharp-load-buffer-file)
+        (with-current-buffer (get-buffer inferior-fsharp-buffer-name)
+          (fsi-tests-wait-for-regex 25 "xxx:\\(.*\\):xxx")
+          (let ((json-str (match-string-no-properties 1)))
+            (unless json-str
+              (warn "FSI output doesn't contain marker: %s" (buffer-substring-no-properties (point-min) (point-max))))
+            (expect json-str :to-equal "{\"X\":2,\"Y\":\"Hello\"}")))))))
+
+(provide 'fsi-tests)
+;;; fsi-tests.el ends here
diff --git a/test/integration-tests.el b/test/integration-tests.el
index d3bec196..6fbe5992 100644
--- a/test/integration-tests.el
+++ b/test/integration-tests.el
@@ -1,6 +1,6 @@
 ;;; integration-tests.el ---                         -*- lexical-binding: t; -*-
 
-;; Copyright (C) 2019  Jürgen Hötzel
+;; Copyright (C) 2019-2023  Jürgen Hötzel
 
 ;; Author: Jürgen Hötzel <juergen@hoetzel.info>
 ;; Keywords: abbrev, abbrev
@@ -24,62 +24,72 @@
 
 ;;; Code:
 
+(load "project")                        ;Emacs 27 workaround: https://github.com/joaotavora/eglot/issues/549
 (require 'buttercup)
 (require 'eglot-fsharp)
-(require 'eglot-tests)
+(load "test/eglot-fsharp-integration-util.el")
 
-(defun eglot-fsharp--sniff-diagnostics ()
-  (eglot--sniffing (:server-notifications s-notifs)
-    (eglot--wait-for (s-notifs 20)
-	(&key _id method &allow-other-keys)
-      (string= method "textDocument/publishDiagnostics"))))
+;; FIXME/HELP WANTED: fsautocomplete process don't seem to terminate on windows (Access denied when trying to install
+;; different version)
+(unless (eq system-type 'windows-nt)
+  (describe "F# LSP Installation"
+            :before-all (setq latest-version (eglot-fsharp--latest-version))
+            (it "succeeds using version 0.77.2"
+                (eglot-fsharp--maybe-install "0.77.2")
+                (expect (eglot-fsharp--installed-version) :to-equal "0.77.2"))
+            (it (format "succeeds using latest version: %s)" latest-version)
+                (eglot-fsharp--maybe-install)
+                (expect (eglot-fsharp--installed-version) :to-equal latest-version))))
 
-(describe "F# LSP server"
-  (it "Can be installed"
-    (eglot-fsharp--maybe-install)
-    (expect (file-exists-p  (eglot-fsharp--path-to-server)) :to-be t))
+(describe "F# LSP Client"
+  :before-all (progn (setq latest-version (eglot-fsharp--latest-version))
+                     (with-temp-buffer (unless (zerop (process-file "dotnet"  nil (current-buffer) nil "restore" "test/Test1"))
+                                         (signal 'file-error (buffer-string))))
+                     (eglot-fsharp--maybe-install)
+                     (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/FileTwo.fs")
+                       (eglot-fsharp--tests-connect 10)
+                       (eglot-fsharp--sniff-method "fsharp/notifyWorkspace")))
+
+  (it "Can be invoked"
+    ;; FIXME: Should use dotnet tool run
+    (expect (process-file (eglot-fsharp--path-to-server) nil nil nil "--version")
+            :to-equal 0))
+  (it "is enabled on F# Files"
+    (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/FileTwo.fs")
+      (expect (type-of (eglot--current-server-or-lose)) :to-be 'eglot-fsautocomplete)))
   (it "shows flymake errors"
-    (with-current-buffer (eglot--find-file-noselect "test/Test1/Error.fs")
-      (eglot--tests-connect 10)
-      (search-forward "nonexisting")
+    (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/Error.fs")
       (flymake-mode t)
       (flymake-start)
+      (eglot-fsharp--sniff-diagnostics "test/Test1/Error.fs")
       (goto-char (point-min))
-      (eglot-fsharp--sniff-diagnostics)
+      (search-forward "nonexisting")
+      (insert "x")
+      (eglot--signal-textDocument/didChange)
       (flymake-goto-next-error 1 '() t)
       (expect (face-at-point) :to-be 'flymake-error )))
-  (it "is enabled on F# Files"
-    (with-current-buffer (eglot--find-file-noselect "test/Test1/FileTwo.fs")
-      (expect (type-of (eglot--current-server-or-lose)) :to-be 'eglot-fsautocomplete)))
   (it "provides completion"
-    (with-current-buffer (eglot--find-file-noselect "test/Test1/FileTwo.fs")
-      (eglot-fsharp--sniff-diagnostics)
+    (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/FileTwo.fs")
       (expect (plist-get (eglot--capabilities (eglot--current-server-or-lose)) :completionProvider) :not :to-be nil)))
   (it "completes function in other modules"
-    (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs")
+    (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/Program.fs")
       (search-forward "X.func")
       (delete-char -3)
-      ;; ERROR in fsautocomplet.exe?  Should block instead of "no type check results"
-      (eglot-fsharp--sniff-diagnostics)
       (completion-at-point)
       (expect (looking-back "X\\.func") :to-be t)))
-  (it "doesn't throw error when definition does not exist"
-    (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs")
-      (eglot-fsharp--sniff-diagnostics)
-      (goto-char 253)
+  (it "finds definition in pervasives"
+    (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/Program.fs")
+      (search-forward "printfn")
       (expect (current-word) :to-equal "printfn") ;sanity check
-      (expect
-       (condition-case err
-	   (call-interactively #'xref-find-definitions)
-	 (user-error
-	  (cadr err)))
-       :to-equal "No definitions found for: LSP identifier at point.")))
+      (call-interactively #'xref-find-definitions)
+      (expect (file-name-nondirectory (buffer-file-name)) :to-equal "fslib-extra-pervasives.fs")))
   (it "finds definitions in other files of Project"
-    (with-current-buffer (eglot--find-file-noselect "test/Test1/Program.fs")
+    (with-current-buffer (eglot-fsharp--find-file-noselect "test/Test1/Program.fs")
       (goto-char 150)
       (expect (current-word) :to-equal "NewObjectType") ;sanity check
       (call-interactively #'xref-find-definitions)
       (expect (file-name-nondirectory (buffer-file-name)) :to-equal "FileTwo.fs"))))
 
+
 (provide 'integration-tests)
 ;;; integration-tests.el ends here
diff --git a/test/nuget.fsx b/test/nuget.fsx
new file mode 100644
index 00000000..4c32d7f9
--- /dev/null
+++ b/test/nuget.fsx
@@ -0,0 +1,6 @@
+#r "nuget: Newtonsoft.Json";;
+open Newtonsoft.Json;;
+
+let o = {| X = 2; Y = "Hello" |};;
+
+printfn "xxx:%s:xxx" (JsonConvert.SerializeObject o);;
