├── emacs ├── test │ ├── FindSlnData │ │ ├── bar.sln │ │ ├── noproj │ │ │ └── test.fs │ │ ├── sln │ │ │ └── foo.sln │ │ └── test.fsproj │ ├── CompileCommandData │ │ ├── proj │ │ │ ├── Makefile │ │ │ ├── test.fs │ │ │ └── test.fsproj │ │ ├── noproj │ │ │ └── test.fs │ │ └── Directory With Spaces │ │ │ ├── noproj │ │ │ └── test.fs │ │ │ └── proj │ │ │ ├── test.fs │ │ │ └── test.fsproj │ ├── Test1 │ │ ├── Script.fsx │ │ ├── FileTwo.fs │ │ ├── Program.fs │ │ └── Test1.fsproj │ ├── Test2 │ │ ├── Main.fs │ │ └── Test2.fsproj │ ├── fsharp-mode-font-tests.el │ ├── fsharp-doc-tests.el │ └── fsharp-mode-tests.el ├── fsharp-mode-pkg.el ├── fsharp-mode-util.el ├── CHANGELOG.md ├── Makefile └── fsharp-doc.el ├── sublimetext ├── FSharp │ ├── fsac │ │ ├── __init__.py │ │ ├── fsac │ │ │ └── KEEPME │ │ ├── client.py │ │ ├── pipe_server.py │ │ ├── response.py │ │ └── request.py │ ├── lib │ │ ├── __init__.py │ │ ├── project.py │ │ ├── editor.py │ │ └── response_processor.py │ ├── tests │ │ ├── __init__.py │ │ ├── lib │ │ │ ├── __init__.py │ │ │ ├── test_editor.py │ │ │ └── test_project.py │ │ ├── syntax_def │ │ │ ├── __init__.py │ │ │ └── test_syntax_def.py │ │ └── tools.py │ ├── sublime_plugin_lib │ │ ├── __init__.py │ │ ├── text.py │ │ ├── sublime.py │ │ ├── context.py │ │ ├── plat.py │ │ ├── collections.py │ │ ├── io.py │ │ ├── testing.py │ │ ├── subprocess.py │ │ ├── LICENSE │ │ ├── filter.py │ │ ├── panels.py │ │ └── fs_completion.py │ ├── FSharp - Run Script.sublime-build │ ├── Default.sublime-keymap │ ├── __init__.py │ ├── test_runner.py │ └── xevents.py ├── .gitattributes ├── Makefile ├── FSharp.sublime-project ├── README.md └── bin │ ├── GetDependencies.ps1 │ ├── publish.sh │ └── Build.ps1 ├── lib ├── nuget │ └── NuGet.exe ├── mono.cecil │ └── Mono.Cecil.dll ├── ndesk-options │ └── NDesk.Options.dll ├── newtonsoft.json │ ├── Newtonsoft.Json.dll │ └── Newtonsoft.Json.pdb └── README ├── vim ├── ftdetect │ └── fsharp.vim ├── ftplugin │ ├── pyvim.py │ ├── hidewin.py │ ├── fsi.py │ └── fsharp.vim ├── install.cmd ├── syntax_checkers │ └── fsharp │ │ └── syntax.vim ├── build.fsx └── Makefile ├── FSharp.AutoComplete ├── test │ └── integration │ │ ├── RobustCommands │ │ ├── nosuchcommand.txt │ │ ├── Project │ │ │ ├── Script.fsx │ │ │ ├── FileTwo.fs │ │ │ ├── Program.fs │ │ │ └── Test1.fsproj │ │ ├── nosuchproject.txt │ │ ├── parsenosuchfile.txt │ │ ├── completenosuchfile.txt │ │ ├── completebadposition.txt │ │ ├── NoSuchCommandRunner.fsx │ │ ├── NoSuchProjectRunner.fsx │ │ ├── CompleteNoSuchFileRunner.fsx │ │ ├── ParseNoSuchFileRunner.fsx │ │ ├── CompleteBadPositionRunner.fsx │ │ ├── CompleteWithoutProjectRunner.fsx │ │ └── completewithoutproject.txt │ │ ├── Test1 │ │ ├── Script.fsx │ │ ├── FileTwo.fs │ │ ├── Program.fs │ │ ├── Test1Runner.fsx │ │ ├── output.txt │ │ └── Test1.fsproj │ │ ├── Test1Json │ │ ├── Script.fsx │ │ ├── FileTwo.fs │ │ ├── Program.fs │ │ ├── Test1JsonRunner.fsx │ │ └── Test1.fsproj │ │ ├── OutOfRange │ │ ├── Script.fsx │ │ ├── output.txt │ │ └── OutOfRangeRunner.fsx │ │ ├── FindDeclarations │ │ ├── Script.fsx │ │ ├── FileTwo.fs │ │ ├── Program.fs │ │ ├── FindDeclRunner.fsx │ │ ├── output.txt │ │ └── FindDecl.fsproj │ │ ├── ErrorTests │ │ ├── Script.fsx │ │ ├── Program.fs │ │ ├── FileTwo.fs │ │ ├── ErrorsRunner.fsx │ │ ├── output.txt │ │ └── Test1.fsproj │ │ ├── ErrorTestsJson │ │ ├── Script.fsx │ │ ├── Program.fs │ │ ├── FileTwo.fs │ │ ├── ErrorsRunner.fsx │ │ ├── output.json │ │ └── Test1.fsproj │ │ ├── SymOpActivePatTooltips │ │ ├── Script.fsx │ │ ├── Runner.fsx │ │ └── output.txt │ │ ├── RawIdTest │ │ ├── Test-Module.fsx │ │ ├── Test-Class.fsx │ │ ├── Runner.fsx │ │ └── output.txt │ │ ├── MultiProj │ │ ├── Proj1 │ │ │ ├── Ops.fs │ │ │ ├── Program.fs │ │ │ ├── Proj1.sln │ │ │ └── Proj1.fsproj │ │ ├── Proj2 │ │ │ ├── Core.fs │ │ │ ├── Program.fs │ │ │ ├── Proj2.sln │ │ │ └── Proj2.fsproj │ │ ├── MultiProjRunner.fsx │ │ └── output.txt │ │ ├── README.md │ │ └── TestHelpers.fsx ├── fake ├── packages.config ├── fake.cmd ├── Makefile ├── Options.fs ├── Debug.fs ├── TipFormatter.fs ├── FSharp.AutoComplete.sln └── README.md ├── FSharp.CompilerBinding ├── packages.config ├── Digraph.fs └── FSharp.CompilerBinding.fsproj ├── appveyor.yml ├── .gitignore ├── .gitattributes ├── CONTRIBUTING.md ├── .travis.yml ├── README.md └── README-old.md /emacs/test/FindSlnData/bar.sln: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emacs/test/FindSlnData/noproj/test.fs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emacs/test/FindSlnData/sln/foo.sln: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emacs/test/FindSlnData/test.fsproj: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sublimetext/FSharp/fsac/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sublimetext/FSharp/fsac/fsac/KEEPME: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sublimetext/FSharp/lib/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sublimetext/FSharp/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emacs/test/CompileCommandData/proj/Makefile: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emacs/test/CompileCommandData/proj/test.fs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sublimetext/FSharp/tests/lib/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sublimetext/FSharp/tests/lib/test_editor.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emacs/test/CompileCommandData/noproj/test.fs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emacs/test/CompileCommandData/proj/test.fsproj: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sublimetext/FSharp/tests/syntax_def/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sublimetext/FSharp/sublime_plugin_lib/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emacs/test/CompileCommandData/Directory With Spaces/noproj/test.fs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emacs/test/CompileCommandData/Directory With Spaces/proj/test.fs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /emacs/test/CompileCommandData/Directory With Spaces/proj/test.fsproj: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsprojects/zarchive-fsharpbinding/HEAD/lib/nuget/NuGet.exe -------------------------------------------------------------------------------- /vim/ftdetect/fsharp.vim: -------------------------------------------------------------------------------- 1 | " F#, fsharp 2 | autocmd BufNewFile,BufRead *.fs,*.fsi,*.fsx set filetype=fsharp 3 | -------------------------------------------------------------------------------- /emacs/test/Test1/Script.fsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | module XA = 4 | let funky x = x + 1 5 | 6 | let val99 = XA.funky 21 7 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/nosuchcommand.txt: -------------------------------------------------------------------------------- 1 | ERROR: Unknown command or wrong arguments 2 | <> 3 | -------------------------------------------------------------------------------- /lib/mono.cecil/Mono.Cecil.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsprojects/zarchive-fsharpbinding/HEAD/lib/mono.cecil/Mono.Cecil.dll -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/Test1/Script.fsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | module XA = 4 | let funky x = x + 1 5 | 6 | let val99 = XA.funky 21 7 | -------------------------------------------------------------------------------- /vim/ftplugin/pyvim.py: -------------------------------------------------------------------------------- 1 | import vim 2 | 3 | def jump(f, cur): 4 | vim.command(':edit ' + f) 5 | vim.current.window.cursor = cur 6 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/Test1Json/Script.fsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | module XA = 4 | let funky x = x + 1 5 | 6 | let val99 = XA.funky 21 7 | -------------------------------------------------------------------------------- /lib/ndesk-options/NDesk.Options.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsprojects/zarchive-fsharpbinding/HEAD/lib/ndesk-options/NDesk.Options.dll -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/OutOfRange/Script.fsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | module XA = 4 | let funky x = x + 1 5 | 6 | let val99 = XA. 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/newtonsoft.json/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsprojects/zarchive-fsharpbinding/HEAD/lib/newtonsoft.json/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /lib/newtonsoft.json/Newtonsoft.Json.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsprojects/zarchive-fsharpbinding/HEAD/lib/newtonsoft.json/Newtonsoft.Json.pdb -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/FindDeclarations/Script.fsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | module XA = 4 | let funky x = x + 1 5 | 6 | let val99 = XA.funky 21 7 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/Project/Script.fsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | module X = 4 | let func x = x + 1 5 | 6 | let val2 = X.func 2 7 | -------------------------------------------------------------------------------- /sublimetext/FSharp/FSharp - Run Script.sublime-build: -------------------------------------------------------------------------------- 1 | { 2 | "target": "run_fs_script", 3 | "path_to_script": "$file", 4 | "selector": "source.fsharp" 5 | } -------------------------------------------------------------------------------- /emacs/test/Test2/Main.fs: -------------------------------------------------------------------------------- 1 | module Test2.Main 2 | 3 | let val2 = List.map ((+) 1) [1;2] 4 | 5 | [] 6 | let main args = 7 | printfn "Hello %A" val2 8 | 0 9 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/ErrorTests/Script.fsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | module X = 4 | let func x = x + 1 5 | 6 | let val2 = X.func 2 7 | 8 | let blast = unnamed 9 | 10 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/ErrorTestsJson/Script.fsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | module X = 4 | let func x = x + 1 5 | 6 | let val2 = X.func 2 7 | 8 | let blast = unnamed 9 | 10 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/nosuchproject.txt: -------------------------------------------------------------------------------- 1 | ERROR: File '/test/integration/RobustCommands/NoSuchProject.fsproj' does not exist 2 | <> 3 | -------------------------------------------------------------------------------- /FSharp.CompilerBinding/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/SymOpActivePatTooltips/Script.fsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | let (|<>|) x y = x + y 4 | let (|..|) x y = x + y 5 | 6 | let val99 = 1 |<>| 1 |..| 1 7 | 8 | let (|Zero|Succ|) n = if n = 0 then Zero else Succ(n-1) 9 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RawIdTest/Test-Module.fsx: -------------------------------------------------------------------------------- 1 | 2 | module X = 3 | let Column1 = 1 4 | 5 | let ``Column Two`` = 1 6 | 7 | let ``Another`Column`` = 1 8 | 9 | X. 10 | 11 | X.``Column T 12 | 13 | X.``Another`C 14 | 15 | -------------------------------------------------------------------------------- /emacs/test/Test1/FileTwo.fs: -------------------------------------------------------------------------------- 1 | module FileTwo 2 | 3 | type Foo = 4 | | Bar 5 | | Qux 6 | 7 | let addition x y = x + y 8 | 9 | let add x y = x + y 10 | 11 | type NewObjectType() = 12 | 13 | member x.Terrific (y : int) : int = 14 | y 15 | -------------------------------------------------------------------------------- /emacs/fsharp-mode-pkg.el: -------------------------------------------------------------------------------- 1 | (define-package 2 | "fsharp-mode" 3 | "1.5.2" 4 | "F# mode for Emacs" 5 | '((auto-complete "1.4") 6 | (popup "0.5") 7 | (pos-tip "0.4.5") 8 | (s "1.3.1") 9 | (dash "1.1.0"))) 10 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RawIdTest/Test-Class.fsx: -------------------------------------------------------------------------------- 1 | 2 | type Y = 3 | static member Column1 = 1 4 | 5 | static member ``Column Two`` = 1 6 | 7 | static member ``Another`Column`` = 1 8 | 9 | Y. 10 | 11 | Y.``Column T 12 | 13 | Y.``Another`C 14 | 15 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/Test1/FileTwo.fs: -------------------------------------------------------------------------------- 1 | module FileTwo 2 | 3 | type Foo = 4 | | Bar 5 | | Qux 6 | 7 | let addition x y = x + y 8 | 9 | let add x y = x + y 10 | 11 | type NewObjectType() = 12 | 13 | member x.Terrific (y : int) : int = 14 | y 15 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/Test1Json/FileTwo.fs: -------------------------------------------------------------------------------- 1 | module FileTwo 2 | 3 | type Foo = 4 | | Bar 5 | | Qux 6 | 7 | let addition x y = x + y 8 | 9 | let add x y = x + y 10 | 11 | type NewObjectType() = 12 | 13 | member x.Terrific (y : int) : int = 14 | y 15 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/MultiProj/Proj1/Ops.fs: -------------------------------------------------------------------------------- 1 | module FileTwo 2 | 3 | type Foo = 4 | | Bar 5 | | Qux 6 | 7 | let addition x y = x + y 8 | 9 | let add x y = x + y 10 | 11 | type NewObjectType() = 12 | 13 | member x.Terrific (y : int) : int = 14 | y 15 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/MultiProj/Proj2/Core.fs: -------------------------------------------------------------------------------- 1 | module FileTwo 2 | 3 | type Foo = 4 | | Bar 5 | | Qux 6 | 7 | let addition x y = x + y 8 | 9 | let add x y = x + y 10 | 11 | type NewObjectType() = 12 | 13 | member x.Terrifying (y : int) : int = 14 | y 15 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/FindDeclarations/FileTwo.fs: -------------------------------------------------------------------------------- 1 | module FileTwo 2 | 3 | type Foo = 4 | | Bar 5 | | Qux 6 | 7 | let addition x y = x + y 8 | 9 | let add x y = x + y 10 | 11 | type NewObjectType() = 12 | 13 | member x.Terrific (y : int) : int = 14 | y 15 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/Project/FileTwo.fs: -------------------------------------------------------------------------------- 1 | module FileTwo 2 | 3 | type Foo = 4 | | Bar 5 | | Qux 6 | 7 | let addition x y = x + y 8 | 9 | let add x y = x + y 10 | 11 | type NewObjectType() = 12 | 13 | member x.Terrific (y : int) : int = 14 | y 15 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/parsenosuchfile.txt: -------------------------------------------------------------------------------- 1 | DATA: project 2 | /test/integration/RobustCommands/Project/FileTwo.fs 3 | /test/integration/RobustCommands/Project/Program.fs 4 | <> 5 | INFO: Background parsing started 6 | <> 7 | -------------------------------------------------------------------------------- /sublimetext/FSharp/tests/tools.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import sublime 4 | 5 | from FSharp.sublime_plugin_lib.testing import SyntaxTest 6 | 7 | 8 | class FSharpSyntaxTest(SyntaxTest): 9 | def setUp(self): 10 | super().setUp() 11 | self._setSyntax('Packages/FSharp/FSharp.tmLanguage') -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/Project/Program.fs: -------------------------------------------------------------------------------- 1 | module X = 2 | let func x = x + 1 3 | 4 | let testval = FileTwo.NewObjectType() 5 | 6 | let val2 = X.func 2 7 | 8 | let val3 = testval.Terrific val2 9 | 10 | [] 11 | let main args = 12 | printfn "Hello %d" val2 13 | 0 14 | -------------------------------------------------------------------------------- /emacs/test/Test1/Program.fs: -------------------------------------------------------------------------------- 1 | module X = 2 | let func x = x + 1 3 | 4 | let testval = FileTwo.NewObjectType() 5 | 6 | let val2 = X.func 2 7 | 8 | let val3 = testval.Terrific val2 9 | 10 | let val4 : FileTwo.NewObjectType = testval 11 | 12 | [] 13 | let main args = 14 | printfn "Hello %d" val2 15 | 0 16 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/ErrorTests/Program.fs: -------------------------------------------------------------------------------- 1 | module X = 2 | let func x = x + 1 3 | 4 | let testval = FileTwo.NewObjectType() 5 | 6 | let val2 = X.func 2 7 | 8 | let val3 = testval.Terrific "hello" 9 | 10 | let val4 = X.func "yo" 11 | 12 | [] 13 | let main args = 14 | printfn "Hello %d" val2 15 | 0 16 | -------------------------------------------------------------------------------- /sublimetext/.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | text=auto 3 | 4 | # These files need to have LF as line terminator, even on Windows. 5 | *.tmSnippet text eol=lf 6 | *.*tmLanguage text eol=lf 7 | messages.json text eol=lf 8 | *.py text eol=lf 9 | *.yaml text eol=lf 10 | *.yml text eol=lf -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/ErrorTestsJson/Program.fs: -------------------------------------------------------------------------------- 1 | module X = 2 | let func x = x + 1 3 | 4 | let testval = FileTwo.NewObjectType() 5 | 6 | let val2 = X.func 2 7 | 8 | let val3 = testval.Terrific "hello" 9 | 10 | let val4 = X.func "yo" 11 | 12 | [] 13 | let main args = 14 | printfn "Hello %d" val2 15 | 0 16 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/ErrorTests/FileTwo.fs: -------------------------------------------------------------------------------- 1 | module FileTwo 2 | 3 | type Foo = 4 | | Bar 5 | | Qux 6 | 7 | let addition x y = x + y 8 | 9 | let add x y = x + y 10 | 11 | type NewObjectType() = 12 | 13 | member x.Terrific (y : int) : int = 14 | y 15 | 16 | let plus x = addition x x x 17 | 18 | let blast = unnamed 19 | 20 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/ErrorTestsJson/FileTwo.fs: -------------------------------------------------------------------------------- 1 | module FileTwo 2 | 3 | type Foo = 4 | | Bar 5 | | Qux 6 | 7 | let addition x y = x + y 8 | 9 | let add x y = x + y 10 | 11 | type NewObjectType() = 12 | 13 | member x.Terrific (y : int) : int = 14 | y 15 | 16 | let plus x = addition x x x 17 | 18 | let blast = unnamed 19 | 20 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/Test1/Program.fs: -------------------------------------------------------------------------------- 1 | module X = 2 | let func x = x + 1 3 | 4 | let testval = FileTwo.NewObjectType() 5 | 6 | let val2 = X.func 2 7 | 8 | let val3 = testval.Terrific val2 9 | 10 | let val4 : FileTwo.NewObjectType = testval 11 | 12 | [] 13 | let main args = 14 | printfn "Hello %d" val2 15 | 0 16 | -------------------------------------------------------------------------------- /vim/ftplugin/hidewin.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | 3 | def addopt(opts): 4 | '''add option to hide the window; Windows only''' 5 | if getattr(subprocess, 'STARTUPINFO', 0) != 0: 6 | si = subprocess.STARTUPINFO() 7 | si.dwFlags = 1 # STARTF_USESHOWWINDOW 8 | si.dwShowWindow = 0 # SW_HIDE 9 | opts['startupinfo'] = si 10 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/completenosuchfile.txt: -------------------------------------------------------------------------------- 1 | DATA: project 2 | /test/integration/RobustCommands/Project/FileTwo.fs 3 | /test/integration/RobustCommands/Project/Program.fs 4 | <> 5 | ERROR: File '/test/integration/RobustCommands/NoSuchFile.fs' not parsed 6 | <> 7 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/Test1Json/Program.fs: -------------------------------------------------------------------------------- 1 | module X = 2 | let func x = x + 1 3 | 4 | let testval = FileTwo.NewObjectType() 5 | 6 | let val2 = X.func 2 7 | 8 | let val3 = testval.Terrific val2 9 | 10 | let val4 : FileTwo.NewObjectType = testval 11 | 12 | [] 13 | let main args = 14 | printfn "Hello %d" val2 15 | 0 16 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/FindDeclarations/Program.fs: -------------------------------------------------------------------------------- 1 | module X = 2 | let func x = x + 1 3 | 4 | let testval = FileTwo.NewObjectType() 5 | 6 | let val2 = X.func 2 7 | 8 | let val3 = testval.Terrific val2 9 | 10 | let val4 : FileTwo.NewObjectType = testval 11 | 12 | [] 13 | let main args = 14 | printfn "Hello %d" val2 15 | 0 16 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/MultiProj/Proj1/Program.fs: -------------------------------------------------------------------------------- 1 | module X = 2 | let func x = x + 1 3 | 4 | let testval = FileTwo.NewObjectType() 5 | 6 | let val2 = X.func 2 7 | 8 | let val3 = testval.Terrific val2 9 | 10 | let val4 : FileTwo.NewObjectType = testval 11 | 12 | [] 13 | let main args = 14 | printfn "Hello %d" val2 15 | 0 16 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/MultiProj/Proj2/Program.fs: -------------------------------------------------------------------------------- 1 | module X = 2 | let func x = x + 1 3 | 4 | let testval = FileTwo.NewObjectType() 5 | 6 | let val2 = X.func 2 7 | 8 | let val3 = testval.Terrifying val2 9 | 10 | let val4 : FileTwo.NewObjectType = testval 11 | 12 | [] 13 | let main args = 14 | printfn "Hello %d" val2 15 | 0 16 | -------------------------------------------------------------------------------- /lib/README: -------------------------------------------------------------------------------- 1 | fsharp -- slightly modified lib/4.0/release binaries from build of 2 | https://github.com/fsharp/fsharp (F# 3.0) tag 3.0.23 3 | 4 | Modifications are to fsharpc and fsharpi script to remove paths 5 | 6 | ndesk-options -- binary release of 0.2.1 7 | 8 | fsautocomplete -- binary release so that MELPA can download it easily 9 | to make installation out of the box -------------------------------------------------------------------------------- /FSharp.AutoComplete/fake: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd `dirname $0` 4 | 5 | FAKE="packages/FAKE/tools/FAKE.exe" 6 | 7 | if [[ ! -e ~/.config/.mono/certs ]]; 8 | then 9 | mozroots --import --sync --quiet 10 | fi 11 | 12 | if [[ ! -e $FAKE ]]; 13 | then 14 | mono ../lib/nuget/NuGet.exe "Install" "FAKE" "-OutputDirectory" "packages" "-ExcludeVersion" 15 | fi 16 | 17 | mono $FAKE "$@" 18 | 19 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /sublimetext/Makefile: -------------------------------------------------------------------------------- 1 | bin_d = $(abspath ./bin) 2 | fsharp_d = $(abspath ./FSharp) 3 | bund_d = $(fsharp_d)/bundled 4 | 5 | 6 | getdeps: 7 | rm -f $(bund_d)/fsautocomplete.zip 8 | wget https://bitbucket.org/guillermooo/fsac/downloads/fsautocomplete.zip -O $(bund_d)/fsautocomplete.zip 9 | 10 | build: 11 | # Publishes tests too. 12 | cd $(bin_d) && ./publish.sh 13 | 14 | install: getdeps build 15 | -------------------------------------------------------------------------------- /vim/install.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | pushd %~dp0 4 | 5 | IF EXIST packages\FAKE\tools\Fake.exe GOTO FAKEINSTALLED 6 | 7 | "..\lib\nuget\NuGet.exe" "install" "FAKE" "-OutputDirectory" "packages" "-ExcludeVersion" "-Prerelease" 8 | 9 | :FAKEINSTALLED 10 | 11 | SET TARGET="All" 12 | 13 | IF NOT [%1]==[] (set TARGET="%1") 14 | 15 | "packages\FAKE\tools\Fake.exe" "build.fsx" "target=%TARGET%" 16 | 17 | popd 18 | 19 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/fake.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | pushd %~dp0 4 | 5 | IF EXIST packages\FAKE\tools\Fake.exe GOTO FAKEINSTALLED 6 | 7 | "..\lib\nuget\NuGet.exe" "install" "FAKE" "-OutputDirectory" "packages" "-ExcludeVersion" "-Prerelease" 8 | 9 | :FAKEINSTALLED 10 | 11 | SET TARGET="All" 12 | 13 | IF NOT [%1]==[] (set TARGET="%1") 14 | 15 | "packages\FAKE\tools\Fake.exe" "build.fsx" "target=%TARGET%" 16 | 17 | popd 18 | 19 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/completebadposition.txt: -------------------------------------------------------------------------------- 1 | DATA: project 2 | /test/integration/RobustCommands/Project/FileTwo.fs 3 | /test/integration/RobustCommands/Project/Program.fs 4 | <> 5 | INFO: Synchronous parsing started 6 | <> 7 | DATA: errors 8 | <> 9 | ERROR: Position is out of range 10 | <> 11 | ERROR: Position is out of range 12 | <> 13 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/NoSuchCommandRunner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 7 | File.Delete "nosuchcommand.txt" 8 | 9 | let p = new FSharpAutoCompleteWrapper() 10 | 11 | p.send "BadCommand\n" 12 | p.send "quit\n" 13 | let output = p.finalOutput () 14 | File.WriteAllText("nosuchcommand.txt", output) 15 | 16 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | EMACSBIN: emacs-24.4-bin-i686-mingw32.7z 3 | FSharpBinding_BlockingTimeout: 1000 4 | FSharpBinding_MaxTimeout: 10000 5 | matrix: 6 | fast_finish: true 7 | install: 8 | - ps: Start-FileDownload "http://downloads.sourceforge.net/project/emacs-bin/releases/$env:EMACSBIN" 9 | - ps: 7z x $env:EMACSBIN -oemacs-local | FIND /V "ing " 10 | build_script: 11 | - cmd: FSharp.AutoComplete\fake.cmd Test 12 | test: off 13 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/NoSuchProjectRunner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 7 | File.Delete "nosuchproject.txt" 8 | 9 | let p = new FSharpAutoCompleteWrapper() 10 | 11 | p.project "NoSuchProject.fsproj" 12 | p.send "quit\n" 13 | let output = p.finalOutput () 14 | File.WriteAllText("nosuchproject.txt", output) 15 | 16 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for compiling and installing F# AutoComplete engine 2 | 3 | .PHONY: all clean integration-test test 4 | 5 | all: ~/.config/.mono/certs 6 | ./fake build 7 | 8 | ~/.config/.mono/certs: 9 | mozroots --import --sync --quiet 10 | 11 | clean: 12 | -rm -fr bin 13 | -rm -fr ../FSharp.CompilerBinding/bin 14 | -rm -fr packages 15 | -rm -rf test/unit/build 16 | 17 | integration-test: all 18 | ./fake integrationtest 19 | 20 | test: integration-test 21 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/CompleteNoSuchFileRunner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 7 | File.Delete "completenosuchfile.txt" 8 | 9 | let p = new FSharpAutoCompleteWrapper() 10 | 11 | p.project "Project/Test1.fsproj" 12 | p.completion "NoSuchFile.fs" 0 0 13 | p.send "quit\n" 14 | let output = p.finalOutput () 15 | File.WriteAllText("completenosuchfile.txt", output) 16 | 17 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/ParseNoSuchFileRunner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 7 | File.Delete "parsenosuchfile.txt" 8 | 9 | let p = new FSharpAutoCompleteWrapper() 10 | 11 | p.project "Project/Test1.fsproj" 12 | p.send "parse \"NoSuchFile.fs\"\nBla bla bla\n<>\n" 13 | p.send "quit\n" 14 | let output = p.finalOutput () 15 | File.WriteAllText("parsenosuchfile.txt", output) 16 | 17 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/ErrorTests/ErrorsRunner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 7 | File.Delete "output.txt" 8 | 9 | let p = new FSharpAutoCompleteWrapper() 10 | 11 | p.project "Test1.fsproj" 12 | p.parse "Program.fs" 13 | p.completion "Program.fs" 6 13 14 | p.parse "Script.fsx" 15 | p.completion "Script.fsx" 6 13 16 | p.send "quit\n" 17 | let output = p.finalOutput () 18 | File.WriteAllText("output.txt", output) 19 | 20 | -------------------------------------------------------------------------------- /sublimetext/FSharp/sublime_plugin_lib/text.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | 6 | def decode_and_clean(data_bytes, encoding='utf-8'): 7 | return clean(decode(data_bytes, encoding)) 8 | 9 | 10 | def decode(data_bytes, encoding='utf-8'): 11 | return data_bytes.decode(encoding) 12 | 13 | 14 | def clean(text): 15 | return text.replace('\r', '') 16 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/CompleteBadPositionRunner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 7 | File.Delete "completebadposition.txt" 8 | 9 | let p = new FSharpAutoCompleteWrapper() 10 | 11 | p.project "Project/Test1.fsproj" 12 | p.parse "Project/Program.fs" 13 | p.completion "Project/Program.fs" 50 0 14 | p.completion "Project/Program.fs" 1 100 15 | p.send "quit\n" 16 | let output = p.finalOutput () 17 | File.WriteAllText("completebadposition.txt", output) 18 | 19 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/CompleteWithoutProjectRunner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 7 | File.Delete "completewithoutproject.txt" 8 | 9 | let p = new FSharpAutoCompleteWrapper() 10 | 11 | p.parse "Project/Script.fsx" 12 | p.completion "Project/Script.fsx" 6 13 13 | p.parse "Project/Program.fs" 14 | p.completion "Project/Program.fs" 4 22 15 | p.send "quit\n" 16 | let output = p.finalOutput () 17 | File.WriteAllText("completewithoutproject.txt", output) 18 | 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # F# 2 | [Bb]in/ 3 | [Oo]bj/ 4 | repository/* 5 | *.suo 6 | *.pidb 7 | *.userprefs 8 | *.GhostDoc.xml 9 | *.user 10 | *.dll 11 | *.pdb 12 | *.cache 13 | *.swp 14 | *.swo 15 | *.swn 16 | *.pyc 17 | *.orig 18 | ======= 19 | *~ 20 | pack/* 21 | lib/NUnit* 22 | lib/FsUnit 23 | 24 | FSharp.AutoComplete/test/unit/build 25 | FSharp.AutoComplete/packages 26 | 27 | # Vim 28 | 29 | vim/packages 30 | 31 | # Emacs 32 | *.elc 33 | emacs/deps 34 | emacs/tmp 35 | 36 | # Sublime Text 37 | *.sublime-workspace 38 | 39 | sublimetext/FSharp/fsac/fsac/*.* 40 | sublimetext/plugin_dev.json 41 | 42 | .DS_Store 43 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/ErrorTestsJson/ErrorsRunner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 7 | File.Delete "output.txt" 8 | 9 | let p = new FSharpAutoCompleteWrapper() 10 | 11 | p.send "outputmode json\n" 12 | p.project "Test1.fsproj" 13 | p.parse "Program.fs" 14 | p.parse "Script.fsx" 15 | Threading.Thread.Sleep(8000) 16 | p.completion "Program.fs" 6 13 17 | p.completion "Script.fsx" 6 13 18 | p.send "quit\n" 19 | let output = p.finalOutput () 20 | File.WriteAllText("output.json", output) 21 | 22 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/completewithoutproject.txt: -------------------------------------------------------------------------------- 1 | INFO: Synchronous parsing started 2 | <> 3 | DATA: errors 4 | <> 5 | DATA: completion 6 | func 7 | <> 8 | INFO: Synchronous parsing started 9 | <> 10 | DATA: errors 11 | [4:14-4:21] ERROR The namespace or module 'FileTwo' is not defined 12 | [8:11-8:27] ERROR Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved. 13 | <> 14 | DATA: completion 15 | <> 16 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | 24 | *.sh text eol=lf 25 | Makefile.orig text eol=lf 26 | configure.sh text eol=lf 27 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | This repository previously contained the advanced editing support for F# for a number of open editors. It is now purely an archive of that development. Please file your issue at one of the below repositories: 2 | 3 | * [F# mode for Emacs](https://github.com/fsharp/emacs-fsharp-mode) 4 | * [F# mode for Vim](https://github.com/fsharp/vim-fsharp) 5 | * [F# mode for Sublime Text](https://github.com/fsharp/sublime-fsharp-package) 6 | * [F# mode for Atom](https://github.com/fsprojects/FSharp.Atom) 7 | * Shared backend component [FsAutoComplete](https://github.com/fsharp/FsAutoComplete) 8 | * [Monodevelop/Xamarin Studio support](https://github.com/fsharp/xamarin-monodevelop-fsharp-addin) 9 | -------------------------------------------------------------------------------- /sublimetext/FSharp/Default.sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | {"keys": ["f12"], "command": "fs_run_fsac", "args": { "cmd": "finddecl"}, "context": [{ "key": "fs_is_code_file"}]}, 3 | {"keys": ["ctrl+.", "ctrl+."], "command": "fs_show_options"}, 4 | {"keys": ["ctrl+.", "ctrl+o"], "command": "show_panel", "args": {"panel": "output.fs.out", "toggle": true}}, 5 | {"keys": ["ctrl+space"], "command": "fs_run_fsac", "args": { "cmd": "completion" }, "context": [{ "key": "fs_is_code_file"}]}, 6 | {"keys": ["."], "command": "fs_dot", "context": [ 7 | { "key": "fs_is_code_file"}, 8 | { "key": "preceding_text", "operator": "regex_contains", "operand": "\\w$"} 9 | ]} 10 | ] -------------------------------------------------------------------------------- /sublimetext/FSharp/sublime_plugin_lib/sublime.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | '''Utilities based on the Sublime Text api. 6 | ''' 7 | import sublime 8 | 9 | 10 | # TODO(guillermooo): make an *_async version too? 11 | def after(timeout, f, *args, **kwargs): 12 | '''Runs @f after @timeout delay in milliseconds. 13 | 14 | @timeout 15 | Delay in milliseconds. 16 | 17 | @f 18 | Function to run passing it @*args and @*kwargs. 19 | ''' 20 | sublime.set_timeout(lambda: f(*args, **kwargs), timeout) 21 | -------------------------------------------------------------------------------- /vim/syntax_checkers/fsharp/syntax.vim: -------------------------------------------------------------------------------- 1 | if exists('g:loaded_syntastic_fsharp_syntax_checker') 2 | finish 3 | endif 4 | let g:loaded_syntastic_fsharp_syntax_checker = 1 5 | let g:fsharp_only_check_errors_on_write = 0 6 | let g:fsharp_xbuild_path = "xbuild" 7 | 8 | let s:save_cpo = &cpo 9 | set cpo&vim 10 | 11 | function! SyntaxCheckers_fsharp_syntax_IsAvailable() dict 12 | return has('python') 13 | endfunction 14 | 15 | function! SyntaxCheckers_fsharp_syntax_GetLocList() dict 16 | return fsharpbinding#python#CurrentErrors() 17 | endfunction 18 | 19 | call g:SyntasticRegistry.CreateAndRegisterChecker({ 20 | \ 'filetype': 'fsharp', 21 | \ 'name': 'syntax'}) 22 | 23 | let &cpo = s:save_cpo 24 | unlet s:save_cpo 25 | 26 | " vim: set et sts=4 sw=4: 27 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: emacs-lisp 2 | 3 | matrix: 4 | fast_finish: true 5 | 6 | before_install: 7 | - sudo apt-key adv --keyserver pgp.mit.edu --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF 8 | - sudo sh -c "echo 'deb http://download.mono-project.com/repo/debian wheezy main' >> /etc/apt/sources.list.d/mono-xamarin.list" 9 | - sudo sh -c "echo 'deb http://download.mono-project.com/repo/debian wheezy-libtiff-compat main' >> /etc/apt/sources.list.d/mono-xamarin.list" 10 | - sudo add-apt-repository -y ppa:cassou/emacs 11 | - sudo apt-get update -qq 12 | 13 | install: 14 | - sudo apt-get install -yq emacs24 emacs24-el emacs24-common-non-dfsg 15 | - sudo apt-get install -yq mono-complete nuget 16 | - sudo apt-get install -yq fsharp 17 | 18 | script: 19 | - FSharp.AutoComplete/fake Test 20 | 21 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RawIdTest/Runner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | (* 7 | * This test is a simple sanity check of a basic run of the program. 8 | * A few completions, files and script. 9 | *) 10 | 11 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 12 | File.Delete "output.txt" 13 | 14 | let p = new FSharpAutoCompleteWrapper() 15 | 16 | p.parse "Test-Module.fsx" 17 | p.parse "Test-Class.fsx" 18 | p.completion "Test-Module.fsx" 9 2 19 | p.completion "Test-Module.fsx" 11 12 20 | p.completion "Test-Module.fsx" 13 13 21 | p.completion "Test-Class.fsx" 9 2 22 | p.completion "Test-Class.fsx" 11 12 23 | p.completion "Test-Class.fsx" 13 13 24 | p.send "quit\n" 25 | let output = p.finalOutput () 26 | File.WriteAllText("output.txt", output) 27 | 28 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/FindDeclarations/FindDeclRunner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | (* 7 | * This test is a simple sanity check of a basic run of the program. 8 | * A few completions, files and script. 9 | *) 10 | 11 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 12 | File.Delete "output.txt" 13 | 14 | let p = new FSharpAutoCompleteWrapper() 15 | 16 | p.project "FindDecl.fsproj" 17 | p.parse "FileTwo.fs" 18 | p.parse "Script.fsx" 19 | p.parse "Program.fs" 20 | p.finddeclaration "Program.fs" 6 15 21 | p.finddeclaration "Program.fs" 8 19 22 | p.finddeclaration "Program.fs" 14 25 23 | p.finddeclaration "Program.fs" 10 19 24 | p.finddeclaration "Script.fsx" 6 16 25 | p.send "quit\n" 26 | let output = p.finalOutput () 27 | File.WriteAllText("output.txt", output) 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Archive of F# Language Support for Open Editors 2 | 3 | This repository previously contained the advanced editing support for F# for a number of open editors. It is now purely an archive of that development. The individual projects can now be found at: 4 | 5 | * [F# mode for Emacs](https://github.com/fsharp/emacs-fsharp-mode) 6 | * [F# mode for Vim](https://github.com/fsharp/vim-fsharp) 7 | * [F# mode for Sublime Text](https://github.com/fsharp/sublime-fsharp-package) 8 | * [F# mode for Atom](https://github.com/fsprojects/FSharp.Atom) 9 | * [F# mode for VS Code](https://github.com/ionide/ionide-vscode-fsharp) 10 | * Shared backend component [FSharp.AutoComplete](https://github.com/fsharp/FSharp.AutoComplete) 11 | * Monodevelop/Xamarin Studio support [FSharpMDXS](https://github.com/mono/monodevelop/tree/master/main/external/fsharpbinding) 12 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/OutOfRange/output.txt: -------------------------------------------------------------------------------- 1 | INFO: Synchronous parsing started 2 | <> 3 | DATA: errors 4 | [6:14-6:15] ERROR Missing qualification after '.' 5 | [6:14-6:15] ERROR Missing qualification after '.' 6 | [6:12-6:14] ERROR The value or constructor 'XA' is not defined 7 | <> 8 | ERROR: Position is out of range 9 | <> 10 | DATA: completion 11 | funky 12 | <> 13 | DATA: tooltip 14 | module XA 15 | 16 | from Script 17 | <> 18 | INFO: No tooltip information 19 | <> 20 | INFO: No tooltip information 21 | <> 22 | ERROR: Position is out of range 23 | <> 24 | DATA: finddecl 25 | /test/integration/OutOfRange/Script.fsx:3:7 26 | <> 27 | ERROR: Could not find declaration 28 | <> 29 | ERROR: Could not find declaration 30 | <> 31 | ERROR: Position is out of range 32 | <> 33 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/OutOfRange/OutOfRangeRunner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | (* 7 | * This test is a simple sanity check of a basic run of the program. 8 | * A few completions, files and script. 9 | *) 10 | 11 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 12 | File.Delete "output.txt" 13 | 14 | let p = new FSharpAutoCompleteWrapper() 15 | 16 | p.parse "Script.fsx" 17 | p.completion "Script.fsx" 6 16 18 | p.completion "Script.fsx" 6 15 19 | p.tooltip "Script.fsx" 6 13 20 | p.tooltip "Script.fsx" 6 14 21 | p.tooltip "Script.fsx" 6 15 22 | p.tooltip "Script.fsx" 6 16 23 | p.finddeclaration "Script.fsx" 6 13 24 | p.finddeclaration "Script.fsx" 6 14 25 | p.finddeclaration "Script.fsx" 6 15 26 | p.finddeclaration "Script.fsx" 6 16 27 | 28 | p.send "quit\n" 29 | let output = p.finalOutput () 30 | File.WriteAllText("output.txt", output) 31 | 32 | -------------------------------------------------------------------------------- /sublimetext/FSharp.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "build_systems": 3 | [ 4 | { 5 | "name": "Run", 6 | "working_dir": "${project_path}/FSharp", 7 | "shell_cmd": "./build.sh", 8 | "windows": { "shell_cmd": "powershell -noprofile -command \" & $project_path\\bin\\Build.ps1 -verbose -restart 4>&1\"" }, 9 | 10 | "variants": [ 11 | { 12 | "name": "FSharp: Test (All)", 13 | "target": "run_fsharp_tests", 14 | }, 15 | 16 | { 17 | "name": "FSharp: Test (This File Only)", 18 | "target": "run_fsharp_tests", 19 | "active_file_only": true 20 | } 21 | ] 22 | } 23 | ], 24 | 25 | "settings": 26 | { 27 | "ensure_new_line_at_eof_on_save": true, 28 | "trim_trailing_white_space_on_save": true, 29 | "default_line_ending": "unix", 30 | "translate_tabs_to_spaces": true 31 | }, 32 | 33 | "folders": 34 | [ 35 | { 36 | "follow_symlinks": true, 37 | "path": "." 38 | } 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /sublimetext/FSharp/sublime_plugin_lib/context.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | import sublime 6 | 7 | 8 | class ContextProviderMixin(object): 9 | '''Provides a method to evaluate contexts. 10 | 11 | Useful with sublime_plugin.EventListeners that need to evaluate contexts. 12 | ''' 13 | def _check(self, value, operator, operand, match_all): 14 | if operator == sublime.OP_EQUAL: 15 | if operand == True: 16 | return value 17 | elif operand == False: 18 | return not value 19 | elif operator == sublime.OP_NOT_EQUAL: 20 | if operand == True: 21 | return not value 22 | elif operand == False: 23 | return value 24 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/ErrorTests/output.txt: -------------------------------------------------------------------------------- 1 | DATA: project 2 | /test/integration/ErrorTests/FileTwo.fs 3 | /test/integration/ErrorTests/Program.fs 4 | <> 5 | INFO: Synchronous parsing started 6 | <> 7 | DATA: errors 8 | [4:14-4:21] ERROR The namespace or module 'FileTwo' is not defined 9 | [8:11-8:27] ERROR Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved. 10 | [10:18-10:22] ERROR This expression was expected to have type 11 | int 12 | but here has type 13 | string 14 | <> 15 | DATA: completion 16 | func 17 | <> 18 | INFO: Synchronous parsing started 19 | <> 20 | DATA: errors 21 | [8:12-8:19] ERROR The value or constructor 'unnamed' is not defined 22 | <> 23 | DATA: completion 24 | func 25 | <> 26 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/README.md: -------------------------------------------------------------------------------- 1 | This directory contains mainly integration tests for the project. 2 | 3 | To run the tests use `make integration-test` or `./fake 4 | IntegrationTest` from the `FSharp.AutoComplete` directory. This will run 5 | `git status` as its last action. The tests are considered to have 6 | passed if there are no changes to the various `*.{txt,json}` files. If a 7 | feature has been changed, then there may be acceptable changes -- 8 | think carefully and then commit them. 9 | 10 | For absolute paths, there is some ad-hoc regex trickery to strip off 11 | the beginning of the path. 12 | 13 | At the moment tests in JSON mode need to have a sleep command entered 14 | after parsing if completion data is going to be requested. This is 15 | because the AppVeyor virtual machines are pretty slow and the 16 | resulting `helptext` data field ends up sometimes containing "(loading 17 | description)" otherwise. This is pretty hackish, but works for now. 18 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/FindDeclarations/output.txt: -------------------------------------------------------------------------------- 1 | DATA: project 2 | /test/integration/FindDeclarations/FileTwo.fs 3 | /test/integration/FindDeclarations/Program.fs 4 | <> 5 | INFO: Synchronous parsing started 6 | <> 7 | DATA: errors 8 | <> 9 | INFO: Synchronous parsing started 10 | <> 11 | DATA: errors 12 | <> 13 | INFO: Synchronous parsing started 14 | <> 15 | DATA: errors 16 | <> 17 | DATA: finddecl 18 | /test/integration/FindDeclarations/Program.fs:2:6 19 | <> 20 | DATA: finddecl 21 | /test/integration/FindDeclarations/FileTwo.fs:13:11 22 | <> 23 | DATA: finddecl 24 | /test/integration/FindDeclarations/Program.fs:6:4 25 | <> 26 | DATA: finddecl 27 | /test/integration/FindDeclarations/FileTwo.fs:11:5 28 | <> 29 | DATA: finddecl 30 | /test/integration/FindDeclarations/Script.fsx:4:6 31 | <> 32 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/Test1/Test1Runner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | (* 7 | * This test is a simple sanity check of a basic run of the program. 8 | * A few completions, files and script. 9 | *) 10 | 11 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 12 | File.Delete "output.txt" 13 | 14 | let p = new FSharpAutoCompleteWrapper() 15 | 16 | p.project "Test1.fsproj" 17 | p.parse "FileTwo.fs" 18 | p.parse "Script.fsx" 19 | p.parse "Program.fs" 20 | p.completion "Script.fsx" 6 15 21 | p.completion "Program.fs" 8 19 22 | p.completion "Program.fs" 4 22 23 | p.completion "Program.fs" 6 13 24 | p.completion "Program.fs" 10 19 25 | p.tooltip "FileTwo.fs" 9 6 26 | p.tooltip "Program.fs" 6 15 27 | p.tooltip "Program.fs" 4 8 28 | p.tooltip "Script.fsx" 4 9 29 | p.declarations "Program.fs" 30 | p.declarations "FileTwo.fs" 31 | p.declarations "Script.fsx" 32 | p.send "quit\n" 33 | let output = p.finalOutput () 34 | File.WriteAllText("output.txt", output) 35 | 36 | -------------------------------------------------------------------------------- /sublimetext/FSharp/sublime_plugin_lib/plat.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | '''Helper functions related to platform-specific issues. 6 | ''' 7 | 8 | import sublime 9 | 10 | from os.path import join 11 | import subprocess 12 | 13 | 14 | def is_windows(): 15 | """Returns `True` if ST is running on Windows. 16 | """ 17 | return sublime.platform() == 'windows' 18 | 19 | 20 | def supress_window(): 21 | """Returns a STARTUPINFO structure configured to supress windows. 22 | Useful, for example, to supress console windows. 23 | 24 | Works only on Windows. 25 | """ 26 | if is_windows(): 27 | startupinfo = subprocess.STARTUPINFO() 28 | startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW 29 | startupinfo.wShowWindow = subprocess.SW_HIDE 30 | return startupinfo 31 | return None 32 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/MultiProj/Proj1/Proj1.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30324.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Proj1", "Proj1.fsproj", "{116CC2F9-F987-4B3D-915A-34CAC04A73DA}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x86 = Debug|x86 11 | Release|x86 = Release|x86 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {116CC2F9-F987-4B3D-915A-34CAC04A73DA}.Debug|x86.ActiveCfg = Debug|x86 15 | {116CC2F9-F987-4B3D-915A-34CAC04A73DA}.Debug|x86.Build.0 = Debug|x86 16 | {116CC2F9-F987-4B3D-915A-34CAC04A73DA}.Release|x86.ActiveCfg = Release|x86 17 | {116CC2F9-F987-4B3D-915A-34CAC04A73DA}.Release|x86.Build.0 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/MultiProj/Proj2/Proj2.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30324.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "Proj2", "Proj2.fsproj", "{116CC2F9-F987-4B3D-915A-34CAC04A73DA}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x86 = Debug|x86 11 | Release|x86 = Release|x86 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {116CC2F9-F987-4B3D-915A-34CAC04A73DA}.Debug|x86.ActiveCfg = Debug|x86 15 | {116CC2F9-F987-4B3D-915A-34CAC04A73DA}.Debug|x86.Build.0 = Debug|x86 16 | {116CC2F9-F987-4B3D-915A-34CAC04A73DA}.Release|x86.ActiveCfg = Release|x86 17 | {116CC2F9-F987-4B3D-915A-34CAC04A73DA}.Release|x86.Build.0 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/SymOpActivePatTooltips/Runner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | (* 7 | * This test runs through tooltips for symbolic operators 8 | * 9 | *) 10 | 11 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 12 | File.Delete "output.txt" 13 | 14 | let p = new FSharpAutoCompleteWrapper() 15 | 16 | p.parse "Script.fsx" 17 | p.tooltip "Script.fsx" 6 13 18 | p.tooltip "Script.fsx" 6 14 19 | p.tooltip "Script.fsx" 6 15 20 | p.tooltip "Script.fsx" 6 16 21 | p.tooltip "Script.fsx" 6 17 22 | p.tooltip "Script.fsx" 6 18 23 | p.tooltip "Script.fsx" 6 19 24 | p.tooltip "Script.fsx" 6 20 25 | p.tooltip "Script.fsx" 6 21 26 | p.tooltip "Script.fsx" 6 22 27 | p.tooltip "Script.fsx" 6 23 28 | p.tooltip "Script.fsx" 6 24 29 | p.tooltip "Script.fsx" 6 25 30 | p.tooltip "Script.fsx" 6 26 31 | p.tooltip "Script.fsx" 8 6 32 | p.tooltip "Script.fsx" 8 10 33 | p.tooltip "Script.fsx" 8 15 34 | p.send "quit\n" 35 | let output = p.finalOutput () 36 | File.WriteAllText("output.txt", output) 37 | 38 | -------------------------------------------------------------------------------- /sublimetext/FSharp/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import logging 4 | import logging.handlers 5 | import logging.config 6 | 7 | import sublime 8 | 9 | from FSharp.lib.editor import Editor 10 | from FSharp.lib.response_processor import process_resp 11 | 12 | 13 | LOGGER_PATH = os.path.join(os.path.dirname(__file__), 'fsharp.log') 14 | 15 | 16 | logger = logging.getLogger('FSharp') 17 | logger.setLevel(logging.ERROR) 18 | 19 | handler = logging.handlers.RotatingFileHandler(LOGGER_PATH, 'a', 2**13) 20 | handler.setLevel(logging.DEBUG) 21 | formatter = logging.Formatter(fmt='%(asctime)s - %(name)s:%(levelname)s: %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') 22 | handler.setFormatter(formatter) 23 | 24 | # ST may reload this file multiple times and `logging` keeps adding handlers. 25 | logger.handlers = [] 26 | logger.addHandler(handler) 27 | 28 | logger.debug('top-level logger initialized') 29 | 30 | logger.debug('starting editor context...') 31 | editor_context = Editor(process_resp) 32 | 33 | 34 | def plugin_unloaded(): 35 | editor_context.fsac.stop() 36 | -------------------------------------------------------------------------------- /sublimetext/FSharp/sublime_plugin_lib/collections.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | 6 | class CircularArray(list): 7 | def __init__(self, *args, **kwargs): 8 | super().__init__(*args, **kwargs) 9 | self.index = None 10 | 11 | def forward(self): 12 | if self.index is None: 13 | self.index = 0 14 | return self[self.index] 15 | 16 | try: 17 | self.index += 1 18 | return self[self.index] 19 | except IndexError: 20 | self.index = 0 21 | return self[self.index] 22 | 23 | def backward(self): 24 | if self.index is None: 25 | self.index = -1 26 | return self[self.index] 27 | 28 | try: 29 | self.index -= 1 30 | return self[self.index] 31 | except IndexError: 32 | self.index = -1 33 | return self[self.index] 34 | -------------------------------------------------------------------------------- /sublimetext/FSharp/sublime_plugin_lib/io.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | import threading 6 | 7 | import os 8 | 9 | 10 | class AsyncStreamReader(threading.Thread): 11 | '''Reads a process stream from an alternate thread. 12 | ''' 13 | def __init__(self, stream, on_data, *args, **kwargs): 14 | ''' 15 | @stream 16 | Stream to read from. 17 | 18 | @on_data 19 | Callback to call with bytes read from @stream. 20 | ''' 21 | super().__init__(*args, **kwargs) 22 | self.stream = stream 23 | self.on_data = on_data 24 | assert self.on_data, 'wrong call: must provide callback' 25 | 26 | def run(self): 27 | while True: 28 | data = self.stream.readline() 29 | if not data: 30 | return 31 | 32 | self.on_data(data) 33 | 34 | 35 | def touch(path): 36 | with open(path, 'wb') as f: 37 | f.close() 38 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/Test1Json/Test1JsonRunner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | (* 7 | * This test is a simple sanity check of a basic run of the program. 8 | * A few completions, files and script. 9 | *) 10 | 11 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 12 | File.Delete "output.txt" 13 | 14 | let p = new FSharpAutoCompleteWrapper() 15 | 16 | p.send "outputmode json\n" 17 | p.project "Test1.fsproj" 18 | p.parse "FileTwo.fs" 19 | p.parse "Script.fsx" 20 | p.parse "Program.fs" 21 | Threading.Thread.Sleep(8000) 22 | p.completion "Script.fsx" 6 15 23 | p.completion "Program.fs" 8 19 24 | p.completion "Program.fs" 4 22 25 | p.completion "Program.fs" 6 13 26 | p.completion "Program.fs" 10 19 27 | p.tooltip "FileTwo.fs" 9 6 28 | p.tooltip "Program.fs" 6 15 29 | p.tooltip "Program.fs" 4 8 30 | p.tooltip "Script.fsx" 4 9 31 | p.finddeclaration "Program.fs" 8 22 32 | p.finddeclaration "Script.fsx" 6 15 33 | p.declarations "Program.fs" 34 | p.declarations "FileTwo.fs" 35 | p.declarations "Script.fsx" 36 | Threading.Thread.Sleep(1000) 37 | p.send "quit\n" 38 | let output = p.finalOutput () 39 | File.WriteAllText("output.json", output) 40 | 41 | -------------------------------------------------------------------------------- /sublimetext/FSharp/tests/syntax_def/test_syntax_def.py: -------------------------------------------------------------------------------- 1 | from FSharp.tests.tools import FSharpSyntaxTest 2 | 3 | 4 | class Test_DoubledQuotedStrings(FSharpSyntaxTest): 5 | def testCanDetectDoubleQuotedStrings(self): 6 | self.append(''' 7 | let foo = "some string here" 8 | 0123456789 9 | 0123456789 10 | 0123456 11 | ''') 12 | actual = self.getFinestScopeNameAtRowCol(1, 11) 13 | self.assertEqual(actual, 'string.quoted.double.fsharp') 14 | 15 | 16 | class Test_TripleQuotedStrings(FSharpSyntaxTest): 17 | def testCanDetectTripleQuotedStrings(self): 18 | self.append(''' 19 | let foo = """some string here""" 20 | 0123456789 21 | 0123456789 22 | 0123456 23 | ''') 24 | actual = self.getFinestScopeNameAtRowCol(1, 13) 25 | self.assertEqual(actual, 'string.quoted.triple.fsharp') 26 | 27 | 28 | class Test_VerbatimStrings(FSharpSyntaxTest): 29 | def testCanDetectVerbatimStrings(self): 30 | self.append(''' 31 | let foo = @"some string here" 32 | 0123456789 33 | 0123456789 34 | 0123456 35 | ''') 36 | actual = self.getFinestScopeNameAtRowCol(1, 12) 37 | self.assertEqual(actual, 'string.quoted.double.verbatim.fsharp') -------------------------------------------------------------------------------- /FSharp.CompilerBinding/Digraph.fs: -------------------------------------------------------------------------------- 1 | namespace FSharp.CompilerBinding 2 | 3 | type Digraph<'n> when 'n : comparison = 4 | Map<'n, Set<'n>> 5 | 6 | module Digraph = 7 | 8 | let addNode (n: 'n) (g: Digraph<'n>) : Digraph<'n> = 9 | match Map.tryFind n g with 10 | | None -> Map.add n Set.empty g 11 | | Some _ -> g 12 | 13 | let addEdge ((n1, n2): 'n * 'n) (g: Digraph<'n>) : Digraph<'n> = 14 | let g' = 15 | match Map.tryFind n2 g with 16 | | None -> addNode n2 g 17 | | Some _ -> g 18 | match Map.tryFind n1 g with 19 | | None -> Map.add n1 (Set.singleton n2) g' 20 | | Some ns -> Map.add n1 (Set.add n2 ns) g' 21 | 22 | let nodes (g: Digraph<'n>) : List<'n> = 23 | Map.fold (fun xs k _ -> k::xs) [] g 24 | 25 | let roots (g: Digraph<'n>) : List<'n> = 26 | List.filter (fun n -> not (Map.exists (fun _ v -> Set.contains n v) g)) (nodes g) 27 | 28 | let topSort (h: Digraph<'n>) : List<'n> = 29 | let rec dfs (g: Digraph<'n>, order: List<'n>, rts: List<'n>) : List<'n> = 30 | if List.isEmpty rts then 31 | order 32 | else 33 | let n = List.head rts 34 | let order' = n::order 35 | let g' = Map.remove n g 36 | let rts' = roots g' 37 | dfs (g', order', rts') 38 | dfs (h, [], roots h) -------------------------------------------------------------------------------- /sublimetext/README.md: -------------------------------------------------------------------------------- 1 | ## FSharp - An F# Package for Sublime Text 2 | 3 | This package provides support for F# development in Sublime Text. 4 | 5 | FSharp is currently a preview and not ready for use. If you want to 6 | contribute to its development, you can read on to learn how to set up a 7 | development environment. 8 | 9 | 10 | ### Developing FSharp 11 | 12 | Pull requests to FSharp are welcome. 13 | 14 | FSharp is only compatible with **Sublime Text 3**. 15 | 16 | 17 | #### General steps 18 | 19 | * Clone this repository to any folder outside of Sublime Text's *Data* folder 20 | * Edit files as needed 21 | * Publish the project using `make install` or `.bin/Build.ps1` 22 | * Restart Sublime Text 23 | * Run the tests via command palette: *FSharp: Run Tests* 24 | 25 | 26 | #### Building 27 | 28 | See below for platform-specific instructions. 29 | 30 | 31 | ### Development environment - Linux/Mac 32 | 33 | Copy *FSharp*'s content manually to *{Sublime Text Data Path}/Packages/FSharp*. 34 | 35 | 36 | ### Development environment - Windows 37 | 38 | #### Requirements 39 | 40 | 41 | You must set `$STDataPath` in your PowerShell session to Sublime Text's *Data* path. 42 | 43 | Build process: 44 | 45 | Run `.\bin\GetDependencies.ps1` once to get dependencies. 46 | Run `.\bin\Build.ps1` to build and publish the files locally. 47 | -------------------------------------------------------------------------------- /sublimetext/FSharp/sublime_plugin_lib/testing.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | '''Provides classes that make it easier to test several aspects of a package. 5 | ''' 6 | 7 | import unittest 8 | 9 | import sublime 10 | 11 | 12 | class ViewTest(unittest.TestCase): 13 | def setUp(self): 14 | self.view = sublime.active_window().new_file() 15 | 16 | def append(self, text): 17 | self.view.run_command('append', {'characters': text}) 18 | 19 | def tearDown(self): 20 | self.view.set_scratch(True) 21 | self.view.close() 22 | 23 | 24 | class SyntaxTest(ViewTest): 25 | def _setSyntax(self, rel_path): 26 | self.view.set_syntax_file(rel_path) 27 | 28 | def getScopeNameAt(self, pt): 29 | return self.view.scope_name(pt) 30 | 31 | def getFinestScopeNameAt(self, pt): 32 | return self.getScopeNameAt(pt).split()[-1] 33 | 34 | def getScopeNameAtRowCol(self, row, col): 35 | text_pt = self.view.text_point(row, col) 36 | return self.getScopeNameAt(text_pt) 37 | 38 | def getFinestScopeNameAtRowCol(self, row, col): 39 | return self.getScopeNameAtRowCol(row, col).split()[-1] 40 | 41 | -------------------------------------------------------------------------------- /sublimetext/bin/GetDependencies.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .DESCRIPTION 3 | Downloads and installs dependencies. 4 | #> 5 | 6 | [CmdletBinding()] 7 | param() 8 | 9 | function IsVerbose { 10 | return $VerbosePreference -eq 'Continue' 11 | } 12 | 13 | function unzip { 14 | param($Source, $Destination) 15 | $shellApp= new-object -com "Shell.Application" 16 | $archive = $shellApp.namespace($Source) 17 | $dest = $shellApp.namespace($Destination) 18 | $dest.copyhere($archive.items()) 19 | } 20 | 21 | $script:thisDir = split-path $MyInvocation.MyCommand.Path -parent 22 | $script:serverDir = resolve-path((join-path $thisDir '../FSharp/fsac/fsac')) 23 | $script:bundledDir = resolve-path((join-path $thisDir '../FSharp/fsac/fsac')) 24 | 25 | # clean up 26 | remove-item (join-path $bundledDir '*.*') -erroraction silentlycontinue 27 | 28 | push-location $bundledDir 29 | write-verbose 'downloading fsautocomplete.zip...' 30 | $client = new-object System.Net.WebClient 31 | $client.DownloadFile('https://bitbucket.org/guillermooo/fsac/downloads/fsac.zip', 32 | "$bundledDir\fsac.zip" ) 33 | 34 | write-verbose 'extracting files...' 35 | unzip (get-item 'fsac.zip').fullname (get-location).providerpath 36 | write-verbose 'cleaning up...' 37 | remove-item 'fsac.zip' 38 | pop-location 39 | 40 | write-verbose 'done' 41 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/MultiProj/MultiProjRunner.fsx: -------------------------------------------------------------------------------- 1 | #load "../TestHelpers.fsx" 2 | open TestHelpers 3 | open System.IO 4 | open System 5 | 6 | Environment.CurrentDirectory <- __SOURCE_DIRECTORY__ 7 | File.Delete "output.txt" 8 | 9 | let p = new FSharpAutoCompleteWrapper() 10 | 11 | p.project "Proj1/Proj1.fsproj" 12 | p.parse "Proj1/Ops.fs" 13 | p.parse "Proj1/Program.fs" 14 | p.completion "Proj1/Program.fs" 8 19 15 | p.completion "Proj1/Program.fs" 4 22 16 | p.completion "Proj1/Program.fs" 6 13 17 | p.completion "Proj1/Program.fs" 10 19 18 | 19 | p.project "Proj2/Proj2.fsproj" 20 | p.parse "Proj2/Core.fs" 21 | p.parse "Proj2/Program.fs" 22 | p.completion "Proj2/Program.fs" 8 19 23 | p.completion "Proj2/Program.fs" 4 22 24 | p.completion "Proj2/Program.fs" 6 13 25 | p.completion "Proj2/Program.fs" 10 19 26 | 27 | p.parse "Proj1/Ops.fs" 28 | p.parse "Proj1/Program.fs" 29 | p.completion "Proj1/Program.fs" 8 19 30 | p.completion "Proj1/Program.fs" 4 22 31 | p.completion "Proj1/Program.fs" 6 13 32 | p.completion "Proj1/Program.fs" 10 19 33 | 34 | p.parse "Proj2/Core.fs" 35 | p.parse "Proj2/Program.fs" 36 | p.completion "Proj2/Program.fs" 8 19 37 | p.completion "Proj2/Program.fs" 4 22 38 | p.completion "Proj2/Program.fs" 6 13 39 | p.completion "Proj2/Program.fs" 10 19 40 | 41 | p.send "quit\n" 42 | let output = p.finalOutput () 43 | File.WriteAllText("output.txt", output) 44 | 45 | -------------------------------------------------------------------------------- /sublimetext/FSharp/sublime_plugin_lib/subprocess.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | from subprocess import Popen 6 | import logging 7 | import os 8 | 9 | from .plat import supress_window 10 | 11 | 12 | _logger = logging.getLogger(__name__) 13 | 14 | 15 | def killwin32(proc): 16 | try: 17 | path = os.path.expandvars("%WINDIR%\\System32\\taskkill.exe") 18 | GenericBinary(show_window=False).start([path, "/pid", str(proc.pid)]) 19 | except Exception as e: 20 | _logger.error(e) 21 | 22 | 23 | class GenericBinary(object): 24 | '''Starts a process. 25 | ''' 26 | def __init__(self, *args, show_window=True): 27 | ''' 28 | @show_window 29 | Windows only. Whether to show a window. 30 | ''' 31 | self.args = args 32 | self.startupinfo = None 33 | if not show_window: 34 | self.startupinfo = supress_window() 35 | 36 | def start(self, args=[], env=None, shell=False, cwd=None): 37 | cmd = self.args + tuple(args) 38 | _logger.debug('running cmd line (GenericBinary): %s', cmd) 39 | Popen(cmd, startupinfo=self.startupinfo, env=env, shell=shell, 40 | cwd=cwd) 41 | -------------------------------------------------------------------------------- /sublimetext/bin/publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copied from: http://stackoverflow.com/a/246128 4 | __FILE_DIR__="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 5 | 6 | # Copies FSharp.sublime-package to Packages/Installed Packages. 7 | publish_package () { 8 | cp -f dist/FSharp.sublime-package "$data_path/Installed Packages" 9 | } 10 | 11 | # Copies FSharp's tests to Packages/FSharp_Tests. 12 | publish_tests () { 13 | mkdir -p "$data_path/Packages/FSharp_Tests" 14 | pushd "$__FILE_DIR__/../FSharp_Tests" 15 | # Copy support files. 16 | cp -f test_runner.py "$data_path/Packages/FSharp_Tests" 17 | cp -f FSharpTests.sublime-commands "$data_path/Packages/FSharp_Tests" 18 | pushd tests 19 | # Copy actual Python packages containing tests. 20 | cp * -rf "$data_path/Packages/FSharp_Tests" 21 | popd 22 | popd 23 | } 24 | 25 | pushd "$__FILE_DIR__/../FSharp" 26 | mkdir -p dist 27 | # Build FSharp.sublime-package. 28 | python builder.py --release dev 29 | case `uname` in 30 | 'Linux') 31 | data_path=~/.config/sublime-text-3 32 | publish_package 33 | publish_tests 34 | ;; 35 | 'Darwin') 36 | data_path=~/Library/Application\ Support/Sublime\ Text \3 37 | publish_package 38 | publish_tests 39 | ;; 40 | esac 41 | popd 42 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/Options.fs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------- 2 | // (c) Robin Neatherway 3 | // -------------------------------------------------------------------------------------- 4 | namespace FSharp.InteractiveAutocomplete 5 | 6 | open System 7 | 8 | module Version = 9 | let string = "FSharp.AutoComplete 0.13.3" 10 | 11 | module Options = 12 | 13 | let verbose = ref false 14 | let timeout = ref 10 15 | 16 | let verboseFilter : Ref>> = ref None 17 | 18 | let p = new NDesk.Options.OptionSet() 19 | Seq.iter (fun (s:string,d:string,a:string -> unit) -> ignore (p.Add(s,d,a))) 20 | [ 21 | "version", "display versioning information", 22 | fun _ -> printfn "%s" Version.string; 23 | exit 0 24 | 25 | "v|verbose", "enable verbose mode", 26 | fun _ -> Debug.verbose := true 27 | 28 | "l|logfile=", "send verbose output to specified log file", 29 | fun s -> try 30 | Debug.output := (IO.File.CreateText(s) :> IO.TextWriter) 31 | with 32 | | e -> printfn "Bad log file: %s" e.Message 33 | exit 1 34 | 35 | "vfilter=", "apply a comma-separated {FILTER} to verbose output", 36 | fun v -> Debug.categories := v.Split(',') |> set |> Some 37 | 38 | "h|?|help", "display this help!", 39 | fun _ -> printfn "%s" Version.string; 40 | p.WriteOptionDescriptions(stdout); 41 | exit 0 42 | ] 43 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RawIdTest/output.txt: -------------------------------------------------------------------------------- 1 | INFO: Synchronous parsing started 2 | <> 3 | DATA: errors 4 | [9:1-9:2] ERROR Missing qualification after '.' 5 | [11:1-11:2] ERROR Missing qualification after '.' 6 | [11:2-11:3] ERROR Unexpected reserved keyword in implementation file 7 | [11:2-11:3] ERROR Unexpected reserved keyword in implementation file 8 | [11:1-11:2] ERROR Missing qualification after '.' 9 | [9:1-9:2] ERROR Missing qualification after '.' 10 | [9:0-9:1] ERROR The value or constructor 'X' is not defined 11 | [11:0-11:1] ERROR The value or constructor 'X' is not defined 12 | <> 13 | INFO: Synchronous parsing started 14 | <> 15 | DATA: errors 16 | [9:1-9:2] ERROR Missing qualification after '.' 17 | [11:1-11:2] ERROR Missing qualification after '.' 18 | [11:2-11:3] ERROR Unexpected reserved keyword in implementation file 19 | [11:2-11:3] ERROR Unexpected reserved keyword in implementation file 20 | [11:1-11:2] ERROR Missing qualification after '.' 21 | [9:1-9:2] ERROR Missing qualification after '.' 22 | [9:0-9:1] ERROR The value or constructor 'Y' is not defined 23 | [11:0-11:1] ERROR The value or constructor 'Y' is not defined 24 | <> 25 | DATA: completion 26 | Another`Column 27 | Column1 28 | <> 29 | DATA: completion 30 | Another`Column 31 | Column1 32 | <> 33 | DATA: completion 34 | Another`Column 35 | Column1 36 | <> 37 | DATA: completion 38 | Another`Column 39 | Column Two 40 | Column1 41 | <> 42 | DATA: completion 43 | Another`Column 44 | Column Two 45 | Column1 46 | <> 47 | DATA: completion 48 | Another`Column 49 | Column Two 50 | Column1 51 | <> 52 | -------------------------------------------------------------------------------- /sublimetext/FSharp/sublime_plugin_lib/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Guillermo López-Anglada. All rights reserved. 2 | Redistribution and use in source and binary forms, with or without 3 | modification, are permitted provided that the following conditions are 4 | met: 5 | * Redistributions of source code must retain the above copyright 6 | notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above 8 | copyright notice, this list of conditions and the following 9 | disclaimer in the documentation and/or other materials provided 10 | with the distribution. 11 | * Neither the name of this software nor the names of its 12 | contributors may be used to endorse or promote products derived 13 | from this software without specific prior written permission. 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/Test1/output.txt: -------------------------------------------------------------------------------- 1 | DATA: project 2 | /test/integration/Test1/FileTwo.fs 3 | /test/integration/Test1/Program.fs 4 | <> 5 | INFO: Synchronous parsing started 6 | <> 7 | DATA: errors 8 | <> 9 | INFO: Synchronous parsing started 10 | <> 11 | DATA: errors 12 | <> 13 | INFO: Synchronous parsing started 14 | <> 15 | DATA: errors 16 | <> 17 | DATA: completion 18 | funky 19 | <> 20 | DATA: completion 21 | Equals 22 | GetHashCode 23 | GetType 24 | Terrific 25 | ToString 26 | <> 27 | DATA: completion 28 | Bar 29 | Foo 30 | NewObjectType 31 | Qux 32 | add 33 | addition 34 | <> 35 | DATA: completion 36 | func 37 | <> 38 | DATA: completion 39 | Bar 40 | Foo 41 | NewObjectType 42 | Qux 43 | add 44 | addition 45 | <> 46 | DATA: tooltip 47 | val add : x:int -> y:int -> int 48 | 49 | Full name: FileTwo.add 50 | <> 51 | DATA: tooltip 52 | val func : x:int -> int 53 | 54 | Full name: Program.X.func 55 | <> 56 | DATA: tooltip 57 | val testval : FileTwo.NewObjectType 58 | 59 | Full name: Program.testval 60 | <> 61 | DATA: tooltip 62 | val funky : x:int -> int 63 | 64 | Full name: Script.XA.funky 65 | <> 66 | DATA: declarations 67 | [1:0-16:0] Program 68 | - [13:4-15:5] main 69 | [1:0-2:20] X 70 | - [2:6-2:20] func 71 | <> 72 | DATA: declarations 73 | [1:0-14:5] FileTwo 74 | - [9:4-9:19] add 75 | - [7:4-7:24] addition 76 | [3:5-5:7] Foo 77 | - [4:4-4:7] Bar 78 | - [5:4-5:7] Qux 79 | [11:5-14:5] NewObjectType 80 | - [13:11-14:5] Terrific 81 | <> 82 | DATA: declarations 83 | [3:0-7:0] Script 84 | [3:0-4:21] XA 85 | - [4:6-4:21] funky 86 | <> 87 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/Debug.fs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------- 2 | // (c) Robin Neatherway 3 | // -------------------------------------------------------------------------------------- 4 | module Debug 5 | 6 | let verbose = ref false 7 | let categories : Ref>> = 8 | ref None 9 | 10 | let output = ref stdout 11 | 12 | [] 13 | type Format<'T> private () = 14 | static let rec mkKn (ty: System.Type) = 15 | if Reflection.FSharpType.IsFunction(ty) then 16 | let _, ran = Reflection.FSharpType.GetFunctionElements(ty) 17 | let f = mkKn ran 18 | Reflection.FSharpValue.MakeFunction(ty, fun _ -> f) 19 | else 20 | box () 21 | 22 | static let instance : 'T = 23 | unbox (mkKn typeof<'T>) 24 | static member Instance = instance 25 | 26 | let inline print (fmt: Printf.TextWriterFormat<'a>) : 'a = 27 | if !verbose then 28 | fprintfn !output fmt 29 | else 30 | Format<_>.Instance 31 | 32 | let inline printc cat fmt = 33 | if !verbose && (match !categories with 34 | | None -> true 35 | | Some c -> Set.contains cat c) then 36 | fprintf !output "[%s] " cat 37 | fprintfn !output fmt 38 | else 39 | Format<_>.Instance 40 | 41 | let private startTime = System.DateTime.Now 42 | 43 | let printTiming (fmt: Printf.TextWriterFormat<'a>) : 'a = 44 | if !verbose then 45 | fprintf !output "%f: " (System.DateTime.Now - startTime).TotalMilliseconds 46 | fprintfn !output fmt 47 | else 48 | Format<_>.Instance 49 | 50 | let inline flush () = 51 | if !verbose then 52 | (!output).Flush() -------------------------------------------------------------------------------- /vim/build.fsx: -------------------------------------------------------------------------------- 1 | // include Fake lib 2 | #r @"packages\FAKE\tools\FakeLib.dll" 3 | open Fake 4 | open System 5 | open System.IO 6 | open System.Text.RegularExpressions 7 | 8 | Target "RestorePackages" (fun _ -> 9 | "packages.config" 10 | |> RestorePackage (fun p -> 11 | { p with 12 | ToolPath = "..\lib\nuget\NuGet.exe" }) 13 | ) 14 | 15 | let vimInstallDir = Environment.ExpandEnvironmentVariables( "%HOMEDRIVE%%HOMEPATH%\\vimfiles\\bundle\\fsharpbinding-vim") 16 | 17 | let vimBinDir = @"ftplugin\bin" 18 | let ftpluginDir = __SOURCE_DIRECTORY__ @@ "ftplugin" 19 | let autoloadDir = __SOURCE_DIRECTORY__ @@ "autoload" 20 | let syntaxDir = __SOURCE_DIRECTORY__ @@ "syntax" 21 | let ftdetectDir = __SOURCE_DIRECTORY__ @@ "ftdetect" 22 | let syntaxCheckersDir = __SOURCE_DIRECTORY__ @@ "syntax_checkers" 23 | 24 | Target "BuildVim" (fun _ -> 25 | CreateDir vimBinDir 26 | MSBuildRelease vimBinDir "Build" [__SOURCE_DIRECTORY__ @@ @"..\FSharp.AutoComplete\FSharp.AutoComplete.fsproj"] 27 | |> Log "Build-Output: " 28 | ) 29 | 30 | Target "Install" (fun _ -> 31 | DeleteDir vimInstallDir 32 | CreateDir vimInstallDir 33 | CopyDir (vimInstallDir @@ "ftplugin") ftpluginDir (fun _ -> true) 34 | CopyDir (vimInstallDir @@ "autoload") autoloadDir (fun _ -> true) 35 | CopyDir (vimInstallDir @@ "syntax") syntaxDir (fun _ -> true) 36 | CopyDir (vimInstallDir @@ "syntax_checkers") syntaxCheckersDir (fun _ -> true) 37 | CopyDir (vimInstallDir @@ "ftdetect") ftdetectDir (fun _ -> true) 38 | ) 39 | 40 | Target "Clean" (fun _ -> 41 | CleanDirs [ vimBinDir; vimInstallDir ]) 42 | 43 | Target "All" id 44 | 45 | "BuildVim" 46 | ==> "Install" 47 | ==> "All" 48 | 49 | RunTargetOrDefault "All" 50 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/SymOpActivePatTooltips/output.txt: -------------------------------------------------------------------------------- 1 | INFO: Synchronous parsing started 2 | <> 3 | DATA: errors 4 | <> 5 | INFO: No tooltip information 6 | <> 7 | DATA: tooltip 8 | val ( |<>| ) : x:int -> y:int -> int 9 | 10 | Full name: Script.( |<>| ) 11 | <> 12 | DATA: tooltip 13 | val ( |<>| ) : x:int -> y:int -> int 14 | 15 | Full name: Script.( |<>| ) 16 | <> 17 | DATA: tooltip 18 | val ( |<>| ) : x:int -> y:int -> int 19 | 20 | Full name: Script.( |<>| ) 21 | <> 22 | DATA: tooltip 23 | val ( |<>| ) : x:int -> y:int -> int 24 | 25 | Full name: Script.( |<>| ) 26 | <> 27 | DATA: tooltip 28 | val ( |<>| ) : x:int -> y:int -> int 29 | 30 | Full name: Script.( |<>| ) 31 | <> 32 | INFO: No tooltip information 33 | <> 34 | INFO: No tooltip information 35 | <> 36 | DATA: tooltip 37 | val ( |..| ) : x:int -> y:int -> int 38 | 39 | Full name: Script.( |..| ) 40 | <> 41 | DATA: tooltip 42 | val ( |..| ) : x:int -> y:int -> int 43 | 44 | Full name: Script.( |..| ) 45 | <> 46 | DATA: tooltip 47 | val ( |..| ) : x:int -> y:int -> int 48 | 49 | Full name: Script.( |..| ) 50 | <> 51 | DATA: tooltip 52 | val ( |..| ) : x:int -> y:int -> int 53 | 54 | Full name: Script.( |..| ) 55 | <> 56 | DATA: tooltip 57 | val ( |..| ) : x:int -> y:int -> int 58 | 59 | Full name: Script.( |..| ) 60 | <> 61 | INFO: No tooltip information 62 | <> 63 | DATA: tooltip 64 | val ( |Zero|Succ| ) : n:int -> Choice 65 | 66 | Full name: Script.( |Zero|Succ| ) 67 | <> 68 | DATA: tooltip 69 | val ( |Zero|Succ| ) : n:int -> Choice 70 | 71 | Full name: Script.( |Zero|Succ| ) 72 | <> 73 | DATA: tooltip 74 | val ( |Zero|Succ| ) : n:int -> Choice 75 | 76 | Full name: Script.( |Zero|Succ| ) 77 | <> 78 | -------------------------------------------------------------------------------- /sublimetext/FSharp/fsac/client.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import logging 3 | import queue 4 | import json 5 | 6 | from .server import requests_queue 7 | from .server import responses_queue 8 | from .server import _internal_comm 9 | 10 | 11 | _logger = logging.getLogger(__name__) 12 | 13 | 14 | def read_responses(responses, messages, resp_proc): 15 | """Reads responses from server and forwards them to @resp_proc. 16 | """ 17 | while True: 18 | try: 19 | data = responses.get(block=True, timeout=5) 20 | if not data: 21 | _logger.warning('no response data to consume; exiting') 22 | break 23 | 24 | try: 25 | if messages.get(block=False) == STOP_SIGNAL: 26 | _logger.info('asked to stop; complying') 27 | break 28 | except: 29 | pass 30 | 31 | _logger.debug('response data read: %s', data) 32 | resp_proc(json.loads(data.decode('utf-8'))) 33 | except queue.Empty: 34 | pass 35 | 36 | _logger.info('stopping reading responses') 37 | 38 | 39 | class FsacClient(object): 40 | """Client for fsac server. 41 | """ 42 | def __init__(self, server, resp_proc): 43 | self.requests = requests_queue 44 | self.server = server 45 | 46 | threading.Thread(target=read_responses, args=(responses_queue, 47 | _internal_comm, 48 | resp_proc)).start() 49 | 50 | def stop(self): 51 | self.server.stop() 52 | 53 | def send_request(self, request): 54 | _logger.debug('sending request: %s', str(request)[:100]) 55 | self.requests.put(request.encode()) 56 | -------------------------------------------------------------------------------- /vim/Makefile: -------------------------------------------------------------------------------- 1 | # Directories 2 | 3 | base_d = $(abspath ..) 4 | bin_d = $(abspath ftplugin/bin) 5 | 6 | # HACK: Vars for manually building the ac binary. 7 | # We should be really able to use the top-level makefile for this... 8 | ac_exe = $(bin_d)/fsautocomplete.exe 9 | ac_fsproj = $(base_d)/FSharp.AutoComplete/FSharp.AutoComplete.fsproj 10 | ac_out = $(base_d)/FSharp.AutoComplete/bin/Debug/ 11 | 12 | # Installation paths. 13 | dest_root = $(HOME)/.vim/bundle/fsharpbinding-vim/ 14 | dest_bin = $(dest_root)/ftplugin/bin/ 15 | 16 | # ---------------------------------------------------------------------------- 17 | 18 | # Building 19 | 20 | fsautocomplete : $(ac_exe) 21 | 22 | $(ac_exe) : $(bin_d) ~/.config/.mono/certs 23 | xbuild $(ac_fsproj) /property:OutputPath="$(bin_d)" 24 | 25 | ~/.config/.mono/certs: 26 | mozroots --import --sync --quiet 27 | 28 | install : $(ac_exe) $(dest_root) $(dest_bin) 29 | rm -r $(dest_root) 30 | mkdir -p $(dest_root)/autoload/fsharpbinding 31 | mkdir -p $(dest_root)/ftdetect 32 | mkdir -p $(dest_root)/ftplugin/bin 33 | mkdir -p $(dest_root)/syntax 34 | mkdir -p $(dest_root)/syntax_checkers/fsharp 35 | 36 | cp syntax/fsharp.vim $(dest_root)/syntax 37 | cp ftdetect/fsharp.vim $(dest_root)/ftdetect/fsharp.vim 38 | cp ftplugin/fsharp.vim $(dest_root)/ftplugin/fsharp.vim 39 | cp ftplugin/pyvim.py $(dest_root)/ftplugin/pyvim.py 40 | cp ftplugin/fsharpvim.py $(dest_root)/ftplugin/fsharpvim.py 41 | cp ftplugin/fsi.py $(dest_root)/ftplugin/fsi.py 42 | cp ftplugin/hidewin.py $(dest_root)/ftplugin/hidewin.py 43 | cp autoload/fsharpbinding/python.vim $(dest_root)/autoload/fsharpbinding/python.vim 44 | cp syntax_checkers/fsharp/syntax.vim $(dest_root)/syntax_checkers/fsharp/syntax.vim 45 | cp -R ftplugin/bin $(dest_root)/ftplugin 46 | 47 | $(dest_root) :; mkdir -p $(dest_root) 48 | $(dest_bin) :; mkdir -p $(dest_bin) 49 | $(bin_d) :; mkdir -p $(bin_d) 50 | 51 | # Cleaning 52 | 53 | clean : 54 | rm -rf $(bin_d) 55 | 56 | .PHONY: fsautocomplete 57 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/TestHelpers.fsx: -------------------------------------------------------------------------------- 1 | open System 2 | open System.Diagnostics 3 | 4 | type FSharpAutoCompleteWrapper() = 5 | 6 | let p = new System.Diagnostics.Process() 7 | 8 | do 9 | p.StartInfo.FileName <- 10 | IO.Path.Combine(__SOURCE_DIRECTORY__, 11 | "../../bin/Debug/fsautocomplete.exe") 12 | p.StartInfo.RedirectStandardOutput <- true 13 | p.StartInfo.RedirectStandardError <- true 14 | p.StartInfo.RedirectStandardInput <- true 15 | p.StartInfo.UseShellExecute <- false 16 | p.Start () |> ignore 17 | 18 | member x.project (s: string) : unit = 19 | fprintf p.StandardInput "project \"%s\"\n" s 20 | 21 | member x.parse (s: string) : unit = 22 | let text = if IO.File.Exists s then IO.File.ReadAllText(s) else "" 23 | fprintf p.StandardInput "parse \"%s\" sync\n%s\n<>\n" s text 24 | 25 | member x.completion (fn: string) (line: int) (col: int) : unit = 26 | fprintf p.StandardInput "completion \"%s\" %d %d\n" fn line col 27 | 28 | member x.tooltip (fn: string) (line: int) (col: int) : unit = 29 | fprintf p.StandardInput "tooltip \"%s\" %d %d\n" fn line col 30 | 31 | member x.finddeclaration (fn: string) (line: int) (col: int) : unit = 32 | fprintf p.StandardInput "finddecl \"%s\" %d %d\n" fn line col 33 | 34 | member x.declarations (fn: string) : unit = 35 | fprintf p.StandardInput "declarations \"%s\"\n" fn 36 | 37 | member x.send (s: string) : unit = 38 | fprintf p.StandardInput "%s" s 39 | 40 | member x.finalOutput () : string = 41 | let s = p.StandardOutput.ReadToEnd() 42 | let t = p.StandardError.ReadToEnd() 43 | p.WaitForExit() 44 | s + t 45 | 46 | let installNuGetPkg s v = 47 | let p = new System.Diagnostics.Process() 48 | 49 | p.StartInfo.FileName <- IO.Path.Combine(__SOURCE_DIRECTORY__, 50 | "../../../lib/nuget/NuGet.exe") 51 | p.StartInfo.Arguments <- " install -ExcludeVersion -Version " + v + " " + s 52 | p.StartInfo.UseShellExecute <- false 53 | p.Start () |> ignore 54 | if not (p.WaitForExit(5 * 60 * 1000)) then 55 | try 56 | p.Kill() 57 | with 58 | | :? System.SystemException as e -> 59 | printfn "Warning: NuGet installation threw an exception: %A" e 60 | 61 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/ErrorTestsJson/output.json: -------------------------------------------------------------------------------- 1 | {"Kind":"project","Data":{"Project":"/test/integration/ErrorTestsJson/Test1.fsproj","Files":["/test/integration/ErrorTestsJson/FileTwo.fs","/test/integration/ErrorTestsJson/Program.fs"],"Output":"/test/integration/ErrorTestsJson/bin/Debug/Test1.exe","References":["/FSharp.Core.dll","/System.Core.dll","/System.dll","/mscorlib.dll"],"Framework":"v4.0"}} 2 | {"Kind":"INFO","Data":"Synchronous parsing started"} 3 | {"Kind":"errors","Data":[{"StartLine":3,"StartLineAlternate":4,"EndLine":3,"EndLineAlternate":4,"StartColumn":14,"EndColumn":21,"Severity":"Error","Message":"The namespace or module 'FileTwo' is not defined","Subcategory":"typecheck","FileName":"/test/integration/ErrorTestsJson/Program.fs"},{"StartLine":7,"StartLineAlternate":8,"EndLine":7,"EndLineAlternate":8,"StartColumn":11,"EndColumn":27,"Severity":"Error","Message":"Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.","Subcategory":"typecheck","FileName":"/test/integration/ErrorTestsJson/Program.fs"},{"StartLine":9,"StartLineAlternate":10,"EndLine":9,"EndLineAlternate":10,"StartColumn":18,"EndColumn":22,"Severity":"Error","Message":"This expression was expected to have type\n int \nbut here has type\n string ","Subcategory":"typecheck","FileName":"/test/integration/ErrorTestsJson/Program.fs"}]} 4 | {"Kind":"INFO","Data":"Synchronous parsing started"} 5 | {"Kind":"errors","Data":[{"StartLine":7,"StartLineAlternate":8,"EndLine":7,"EndLineAlternate":8,"StartColumn":12,"EndColumn":19,"Severity":"Error","Message":"The value or constructor 'unnamed' is not defined","Subcategory":"typecheck","FileName":"/test/integration/ErrorTestsJson/Script.fsx"}]} 6 | {"Kind":"helptext","Data":{"func":"val func : x:int -> int"}} 7 | {"Kind":"completion","Data":["func"]} 8 | {"Kind":"helptext","Data":{"func":"val func : x:int -> int"}} 9 | {"Kind":"completion","Data":["func"]} 10 | -------------------------------------------------------------------------------- /sublimetext/FSharp/sublime_plugin_lib/filter.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | from subprocess import Popen 6 | from subprocess import PIPE 7 | from subprocess import TimeoutExpired 8 | import threading 9 | import logging 10 | 11 | from .plat import supress_window 12 | from .text import clean 13 | from .text import decode 14 | 15 | 16 | _logger = logging.getLogger(__name__) 17 | 18 | 19 | class TextFilter(object): 20 | '''Filters text through an external program (sync). 21 | ''' 22 | def __init__(self, args, timeout=10): 23 | self.args = args 24 | self.timeout = timeout 25 | # Encoding the external program likes to receive. 26 | self.in_encoding = 'utf-8' 27 | # Encoding the external program will emit. 28 | self.out_encoding = 'utf-8' 29 | 30 | self._proc = None 31 | 32 | def encode(self, text): 33 | return text.encode(self.in_encoding) 34 | 35 | def _start(self): 36 | try: 37 | self._proc = Popen(self.args, 38 | stdout=PIPE, 39 | stderr=PIPE, 40 | stdin=PIPE, 41 | startupinfo=supress_window()) 42 | except OSError as e: 43 | _logger.error('while starting text filter program: %s', e) 44 | return 45 | 46 | def filter(self, input_text): 47 | self._start() 48 | try: 49 | in_bytes = self.encode(input_text) 50 | out_bytes, err_bytes = self._proc.communicate(in_bytes, 51 | self.timeout) 52 | if err_bytes: 53 | _logger.error('while filtering text: %s', 54 | clean(decode(err_bytes, self.out_encoding))) 55 | return 56 | 57 | return clean(decode(out_bytes, self.out_encoding)) 58 | 59 | except TimeoutExpired: 60 | _logger.debug('text filter program response timed out') 61 | return 62 | 63 | except Exception as e: 64 | _logger.error('while running TextFilter: %s', e) 65 | return 66 | -------------------------------------------------------------------------------- /sublimetext/FSharp/test_runner.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | import sublime 6 | import sublime_plugin 7 | 8 | import os 9 | import unittest 10 | import contextlib 11 | import threading 12 | 13 | 14 | from FSharp.sublime_plugin_lib.panels import OutputPanel 15 | 16 | 17 | class RunFsharpTests(sublime_plugin.WindowCommand): 18 | '''Runs tests and displays the result. 19 | 20 | - Do not use ST while tests are running. 21 | 22 | @working_dir 23 | Required. Should be the parent of the top-level directory for `tests`. 24 | 25 | @loader_pattern 26 | Optional. Only run tests matching this glob. 27 | 28 | @active_file_only 29 | Optional. Only run tests in the active file in ST. Shadows 30 | @loader_pattern. 31 | 32 | To use this runner conveniently, open the command palette and select one 33 | of the `Build: Dart - Test *` commands. 34 | ''' 35 | @contextlib.contextmanager 36 | def chdir(self, path=None): 37 | old_path = os.getcwd() 38 | if path is not None: 39 | assert os.path.exists(path), "'path' is invalid {}".format(path) 40 | os.chdir(path) 41 | yield 42 | if path is not None: 43 | os.chdir(old_path) 44 | 45 | def run(self, **kwargs): 46 | with self.chdir(kwargs.get('working_dir')): 47 | p = os.path.join(os.getcwd(), 'tests') 48 | patt = kwargs.get('loader_pattern', 'test*.py',) 49 | # TODO(guillermooo): I can't get $file to expand in the build 50 | # system. It should be possible to make the following code simpler 51 | # with it. 52 | if kwargs.get('active_file_only') is True: 53 | patt = os.path.basename(self.window.active_view().file_name()) 54 | suite = unittest.TestLoader().discover(p, pattern=patt) 55 | 56 | file_regex = r'^\s*File\s*"([^.].*?)",\s*line\s*(\d+),.*$' 57 | display = OutputPanel('fs.tests', file_regex=file_regex) 58 | display.show() 59 | runner = unittest.TextTestRunner(stream=display, verbosity=1) 60 | 61 | def run_and_display(): 62 | runner.run(suite) 63 | 64 | threading.Thread(target=run_and_display).start() -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/MultiProj/output.txt: -------------------------------------------------------------------------------- 1 | DATA: project 2 | /test/integration/MultiProj/Proj1/Ops.fs 3 | /test/integration/MultiProj/Proj1/Program.fs 4 | <> 5 | INFO: Synchronous parsing started 6 | <> 7 | DATA: errors 8 | <> 9 | INFO: Synchronous parsing started 10 | <> 11 | DATA: errors 12 | <> 13 | DATA: completion 14 | Equals 15 | GetHashCode 16 | GetType 17 | Terrific 18 | ToString 19 | <> 20 | DATA: completion 21 | Bar 22 | Foo 23 | NewObjectType 24 | Qux 25 | add 26 | addition 27 | <> 28 | DATA: completion 29 | func 30 | <> 31 | DATA: completion 32 | Bar 33 | Foo 34 | NewObjectType 35 | Qux 36 | add 37 | addition 38 | <> 39 | DATA: project 40 | /test/integration/MultiProj/Proj2/Core.fs 41 | /test/integration/MultiProj/Proj2/Program.fs 42 | <> 43 | INFO: Synchronous parsing started 44 | <> 45 | DATA: errors 46 | <> 47 | INFO: Synchronous parsing started 48 | <> 49 | DATA: errors 50 | <> 51 | DATA: completion 52 | Equals 53 | GetHashCode 54 | GetType 55 | Terrifying 56 | ToString 57 | <> 58 | DATA: completion 59 | Bar 60 | Foo 61 | NewObjectType 62 | Qux 63 | add 64 | addition 65 | <> 66 | DATA: completion 67 | func 68 | <> 69 | DATA: completion 70 | Bar 71 | Foo 72 | NewObjectType 73 | Qux 74 | add 75 | addition 76 | <> 77 | INFO: Synchronous parsing started 78 | <> 79 | DATA: errors 80 | <> 81 | INFO: Synchronous parsing started 82 | <> 83 | DATA: errors 84 | <> 85 | DATA: completion 86 | Equals 87 | GetHashCode 88 | GetType 89 | Terrific 90 | ToString 91 | <> 92 | DATA: completion 93 | Bar 94 | Foo 95 | NewObjectType 96 | Qux 97 | add 98 | addition 99 | <> 100 | DATA: completion 101 | func 102 | <> 103 | DATA: completion 104 | Bar 105 | Foo 106 | NewObjectType 107 | Qux 108 | add 109 | addition 110 | <> 111 | INFO: Synchronous parsing started 112 | <> 113 | DATA: errors 114 | <> 115 | INFO: Synchronous parsing started 116 | <> 117 | DATA: errors 118 | <> 119 | DATA: completion 120 | Equals 121 | GetHashCode 122 | GetType 123 | Terrifying 124 | ToString 125 | <> 126 | DATA: completion 127 | Bar 128 | Foo 129 | NewObjectType 130 | Qux 131 | add 132 | addition 133 | <> 134 | DATA: completion 135 | func 136 | <> 137 | DATA: completion 138 | Bar 139 | Foo 140 | NewObjectType 141 | Qux 142 | add 143 | addition 144 | <> 145 | -------------------------------------------------------------------------------- /emacs/fsharp-mode-util.el: -------------------------------------------------------------------------------- 1 | ;;; fsharp-mode-util.el --- Support for F# interactive 2 | 3 | ;; Copyright (C) 1997 INRIA 4 | 5 | ;; Author: 2015 Robin Neatherway 6 | ;; Maintainer: Robin Neatherway 7 | ;; Keywords: languages 8 | 9 | ;; This file is not part of GNU Emacs. 10 | 11 | ;; This file is free software; you can redistribute it and/or modify 12 | ;; it under the terms of the GNU General Public License as published by 13 | ;; the Free Software Foundation; either version 3, or (at your option) 14 | ;; any later version. 15 | 16 | ;; This file is distributed in the hope that it will be useful, 17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | ;; GNU General Public License for more details. 20 | 21 | ;; You should have received a copy of the GNU General Public License 22 | ;; along with GNU Emacs; see the file COPYING. If not, write to 23 | ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 24 | ;; Boston, MA 02110-1301, USA. 25 | 26 | (with-no-warnings (require 'cl)) 27 | (require 'dash) 28 | 29 | (defvar fsharp-ac-using-mono 30 | (case system-type 31 | ((windows-nt cygwin msdos) nil) 32 | (otherwise t)) 33 | "Whether the .NET runtime in use is mono. Defaults to `nil' for 34 | Microsoft platforms (including Cygwin), `t' for all *nix.") 35 | 36 | (defun fsharp-mode--program-files-x86 () 37 | (file-name-as-directory 38 | (car (-drop-while 'not 39 | (list (getenv "ProgramFiles(x86)") 40 | (getenv "ProgramFiles") 41 | "C:\\Program Files (x86)"))))) 42 | 43 | (defun fsharp-mode--msbuild-find (exe) 44 | (if fsharp-ac-using-mono 45 | (executable-find exe) 46 | (let* ((searchdirs (--map (concat (fsharp-mode--program-files-x86) 47 | "MSBuild/" it "/Bin") 48 | '("14.0" "13.0" "12.0"))) 49 | (exec-path (append searchdirs exec-path))) 50 | (executable-find exe)))) 51 | 52 | (defun fsharp-mode--executable-find (exe) 53 | (if fsharp-ac-using-mono 54 | (executable-find exe) 55 | (let* ((searchdirs (--map (concat (fsharp-mode--program-files-x86) 56 | "Microsoft SDKs/F#/" it "/Framework/v4.0") 57 | '("4.0" "3.1" "3.0"))) 58 | (exec-path (append searchdirs exec-path))) 59 | (executable-find exe)))) 60 | 61 | (provide 'fsharp-mode-util) 62 | 63 | ;;; fsharp-mode-util.el ends here 64 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/TipFormatter.fs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------- 2 | // (c) Tomas Petricek, http://tomasp.net/blog 3 | // -------------------------------------------------------------------------------------- 4 | module internal FSharp.InteractiveAutocomplete.TipFormatter 5 | 6 | open System.Text 7 | open Microsoft.FSharp.Compiler.SourceCodeServices 8 | 9 | // -------------------------------------------------------------------------------------- 10 | // Formatting of tool-tip information displayed in F# IntelliSense 11 | // -------------------------------------------------------------------------------------- 12 | 13 | let private buildFormatComment cmt (sb:StringBuilder) = 14 | match cmt with 15 | | FSharpXmlDoc.Text s -> sb.AppendLine(s) 16 | // For 'XmlCommentSignature' we could get documentation from 'xml' 17 | // files, but I'm not sure whether these are available on Mono 18 | | _ -> sb 19 | 20 | // If 'isSingle' is true (meaning that this is the only tip displayed) 21 | // then we add first line "Multiple overloads" because MD prints first 22 | // int in bold (so that no overload is highlighted) 23 | let private buildFormatElement isSingle el (sb:StringBuilder) = 24 | match el with 25 | | FSharpToolTipElement.None -> sb 26 | | FSharpToolTipElement.Single(it, comment) -> 27 | sb.AppendLine(it) |> buildFormatComment comment 28 | | FSharpToolTipElement.Group(items) -> 29 | let items, msg = 30 | if items.Length > 10 then 31 | (items |> Seq.take 10 |> List.ofSeq), 32 | sprintf " (+%d other overloads)" (items.Length - 10) 33 | else items, null 34 | if (isSingle && items.Length > 1) then 35 | sb.AppendLine("Multiple overloads") |> ignore 36 | for (it, comment) in items do 37 | sb.AppendLine(it) |> buildFormatComment comment |> ignore 38 | if msg <> null then sb.AppendFormat(msg) else sb 39 | | FSharpToolTipElement.CompositionError(err) -> 40 | sb.Append("Composition error: " + err) 41 | 42 | let private buildFormatTip tip (sb:StringBuilder) = 43 | match tip with 44 | | FSharpToolTipText([single]) -> sb |> buildFormatElement true single 45 | | FSharpToolTipText(its) -> 46 | sb.AppendLine("Multiple items") |> ignore 47 | its |> Seq.mapi (fun i it -> i = 0, it) |> Seq.fold (fun sb (first, item) -> 48 | if not first then sb.AppendLine("\n--------------------\n") |> ignore 49 | sb |> buildFormatElement false item) sb 50 | 51 | /// Format tool-tip that we get from the language service as string 52 | let formatTip tip = 53 | (buildFormatTip tip (new StringBuilder())).ToString().Trim('\n', '\r').Replace("\r","") 54 | -------------------------------------------------------------------------------- /emacs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.5.2 (2015-03-20) 2 | 3 | Bugfixes: 4 | - #973: Force comint-process-echoes to nil to avoid hangs 5 | 6 | ## 1.5.1 (2015-01-14) 7 | 8 | Bugfixes: 9 | - #923: Autocompletion not working on Emacs 24.4+ on Windows 10 | 11 | ## 1.5.0 (2014-11-25) 12 | 13 | Incorporate FSharp.AutoComplete version 0.13.3, which has corrected help text for the parse command and uses FCS 0.0.81. 14 | 15 | Features: 16 | - #235: Support multiple projects simultaneously 17 | 18 | Bugfixes: 19 | - #824: Emacs should give a better error message if fsautocomplete not found 20 | - #808: C-c C-p gives an error if no project file above current file's directory 21 | - #790: Can't make fsac requests in indirect buffers 22 | - #754: Compiler warnings when installing fsharp-mode from MELPA 23 | 24 | ## 1.4.2 (2014-10-30) 25 | 26 | Incorporate FSharp.AutoComplete version 0.13.2, which returns more information if the project parsing fails. 27 | 28 | Features: 29 | - #811: Return exception message on project parsing fail 30 | 31 | ## 1.4.1 (2014-10-30) 32 | 33 | Incorporate FSharp.AutoComplete version 0.13.1, which contains a fix for goto definition. 34 | 35 | Bugfixes: 36 | - #787: Correct off-by-one error in fsac goto definition 37 | 38 | ## 1.4.0 (2014-10-26) 39 | 40 | The main feature of this release is that the project parsing logic has 41 | been moved to FSharp.Compiler.Service as part of fixing #728. 42 | 43 | Features: 44 | - #319: Better error feedback when no completion data available 45 | - #720: Rationalise emacs testing, also fixed #453 46 | 47 | Bugfixes: 48 | - #765: Do not offer completions in irrelevant locations (strings/comments) 49 | - #721: Tests for Emacs syntax highlighting, and resultant fixes 50 | - #248: Run executable file now uses output from FSharp.AutoComplete 51 | - #728: Fix project support on Windows 52 | 53 | ## 1.3.0 (2014-08-28) 54 | 55 | Changes by @rneatherway unless otherwise noted. 56 | 57 | Major changes in this release are performance improvements thanks to @juergenhoetzel (avoiding parsing the current buffer unless necessary), and 58 | fixes for syntax highlighting. 59 | 60 | 61 | Features: 62 | - #481: Only parse the current buffer if it is was modified (@juergenhoetzel) 63 | 64 | Bugfixes: 65 | - #619: Disable FSI syntax highlighting 66 | - #670: Prevent double dots appearing during completion 67 | - #485: Fetch SSL certs before building exe in emacs dir 68 | - #496: Corrections to emacs syntax highlighting 69 | - #597: Highlight preprocessor and async 70 | - #605: Add FSI directives to syntax highlighting of emacs 71 | - #571: Correct range-check for emacs support 72 | - #572: Ensure fsi prompt is readonly 73 | - #452: Fetch SSL certs before building exe in emacs dir 74 | 75 | -------------------------------------------------------------------------------- /sublimetext/FSharp/lib/project.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | import os 6 | 7 | from FSharp.sublime_plugin_lib.path import find_file_by_extension 8 | from FSharp.sublime_plugin_lib.path import extension_equals 9 | 10 | 11 | def find_fsproject (start): 12 | '''Find a .fsproject file starting at @start path. 13 | 14 | Returns the path to the file or `None` if not found. 15 | ''' 16 | return find_file_by_extension(start, 'fsproj') 17 | 18 | 19 | class FSharpFile (object): 20 | '''Inspects a file for interesting properties from the plugin's POV. 21 | ''' 22 | def __init__(self, view_or_fname): 23 | """ 24 | @view_or_fname 25 | A Sublime Text view or a file name. 26 | """ 27 | assert view_or_fname, 'wrong arg: %s' % view_or_fname 28 | self.view_or_fname = view_or_fname 29 | 30 | @property 31 | def path(self): 32 | try: 33 | return self.view_or_fname.file_name() 34 | except AttributeError: 35 | return self.view_or_fname 36 | 37 | @property 38 | def is_fsharp_file(self): 39 | return any((self.is_code_file, 40 | self.is_script_file, 41 | self.is_project_file)) 42 | 43 | @property 44 | def is_code(self): 45 | return (self.is_code_file or self.is_script_file) 46 | 47 | @property 48 | def is_code_file(self): 49 | return extension_equals(self.view_or_fname, '.fs') 50 | 51 | @property 52 | def is_script_file(self): 53 | return (extension_equals(self.view_or_fname, '.fsx') or 54 | extension_equals(self.view_or_fname, '.fsi')) 55 | 56 | @property 57 | def is_project_file(self): 58 | return extension_equals(self.view_or_fname, '.fsproj') 59 | 60 | 61 | class FSharpProjectFile (object): 62 | def __init__(self, path): 63 | assert path.endswith('fsproj'), 'wrong fsproject path: %s' % path 64 | self.path = path 65 | self.parent = os.path.dirname (self.path) 66 | 67 | def __eq__(self, other): 68 | # todo: improve comparison 69 | return os.path.normpath(self.path) == os.path.normpath(other.path) 70 | 71 | def governs(self, fname): 72 | return fname.startswith(self.parent) 73 | 74 | @classmethod 75 | def from_path(cls, path): 76 | ''' 77 | @path 78 | A path to a file or directory. 79 | ''' 80 | fs_project = find_fsproject (path) 81 | if not fs_project: 82 | return None 83 | return FSharpProjectFile (fs_project) -------------------------------------------------------------------------------- /emacs/test/fsharp-mode-font-tests.el: -------------------------------------------------------------------------------- 1 | ;;; fsharp-mode-font-tests.el --- Regression test for FSharp font lock 2 | 3 | ;; Keywords: faces languages 4 | ;; Created: 2014-09-13 5 | ;; Version: 0.0.0 6 | 7 | ;; This program is free software: you can redistribute it and/or modify 8 | ;; it under the terms of the GNU General Public License as published by 9 | ;; the Free Software Foundation, either version 3 of the License, or 10 | ;; (at your option) any later version. 11 | 12 | ;; This program is distributed in the hope that it will be useful, 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ;; GNU General Public License for more details. 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with this program. If not, see . 19 | 20 | ;;; Commentary: 21 | 22 | ;; Regression test of `fsharp-mode-face', a package providing 23 | ;; font-lock rules for F#. This module verifies fontification of a 24 | ;; number of files taken from real projects. This is done by keeing a 25 | ;; text representation of the fontification using `faceup' markup, in 26 | ;; addition to the original source file. 27 | ;; 28 | ;; To regenerate the faceup representation, use M-x faceup-write-file RET. 29 | ;; 30 | ;; `faceup' is located at https://github.com/Lindydancer/faceup 31 | ;; 32 | ;; The actual check is performed using `ert' (Emacs Regression Test), 33 | ;; with a font-lock test function provided by `faceup'. 34 | 35 | ;;; Code: 36 | 37 | (require 'faceup) 38 | 39 | (defvar fsharp-mode-face-test-file-name (faceup-this-file-directory) 40 | "The file name of this file.") 41 | 42 | (defun fsharp-mode-face-test-apps (file) 43 | "Test that FILE is fontifies as the .faceup file describes. 44 | 45 | FILE is interpreted as relative to this source directory." 46 | (faceup-test-font-lock-file 'fsharp-mode 47 | (concat 48 | fsharp-mode-face-test-file-name 49 | file))) 50 | (faceup-defexplainer fsharp-mode-face-test-apps) 51 | 52 | 53 | (ert-deftest fsharp-mode-face-file-test () 54 | (let ((coding-system-for-read 'utf-8)) 55 | (should (fsharp-mode-face-test-apps "apps/FQuake3/NativeMappings.fs")) 56 | (should (fsharp-mode-face-test-apps "apps/FSharp.Compatibility/Format.fs")))) 57 | 58 | 59 | (defun fsharp-font-lock-test (faceup) 60 | (faceup-test-font-lock-string 'fsharp-mode faceup)) 61 | (faceup-defexplainer fsharp-font-lock-test) 62 | 63 | (ert-deftest fsharp-mode-face-test-snippets () 64 | (should (fsharp-font-lock-test "«k:let» «v:x» = is a keyword")) 65 | (should (fsharp-font-lock-test "«k:open» «t:FSharp.Charting»"))) 66 | 67 | ;;; fsharp-mode-font-tests.el ends here 68 | -------------------------------------------------------------------------------- /sublimetext/FSharp/fsac/pipe_server.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | '''Wraps a process to make it act as a pipe server. Takes care of supressing 6 | console windows under Windows and other housekeeping. 7 | ''' 8 | 9 | import subprocess 10 | from subprocess import PIPE 11 | from subprocess import Popen 12 | import os 13 | import threading 14 | from contextlib import contextmanager 15 | 16 | 17 | @contextmanager 18 | def pushd(to): 19 | old = os.getcwd() 20 | try: 21 | os.chdir(to) 22 | # TODO(guillermooo): makes more sense to return 'old' 23 | yield to 24 | finally: 25 | os.chdir(old) 26 | 27 | 28 | def supress_window(): 29 | """Returns a STARTUPINFO structure configured to supress windows. 30 | Useful, for example, to supress console windows. 31 | 32 | Works only on Windows. 33 | """ 34 | if os.name == 'nt': 35 | startupinfo = subprocess.STARTUPINFO() 36 | startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW 37 | startupinfo.wShowWindow = subprocess.SW_HIDE 38 | return startupinfo 39 | return None 40 | 41 | 42 | # _logger = PluginLogger(__name__) 43 | 44 | 45 | class PipeServer(object): 46 | '''Starts as process and communicates with it via pipes. 47 | ''' 48 | status_lock = threading.RLock() 49 | 50 | def __init__(self, args): 51 | self.proc = None 52 | self.args = args 53 | 54 | @property 55 | def is_running(self): 56 | '''Returns `True` if the server seems to be responsive. 57 | ''' 58 | try: 59 | with PipeServer.status_lock: 60 | return not self.proc.stdin.closed 61 | except AttributeError: 62 | # _logger.debug('PipeServer not started yet') 63 | return 64 | 65 | def start(self, working_dir='.'): 66 | with PipeServer.status_lock: 67 | if self.is_running: 68 | # _logger.debug( 69 | # 'tried to start an already running PipeServer; aborting') 70 | return 71 | 72 | with pushd(working_dir): 73 | # _logger.debug('starting PipeServer with args: %s', self.args) 74 | self.proc = Popen(self.args, 75 | stdout=PIPE, 76 | stdin=PIPE, 77 | stderr=PIPE, 78 | startupinfo=supress_window()) 79 | 80 | def stop(self): 81 | # _logger.debug('stopping PipeServer...') 82 | self.proc.stdin.close() 83 | self.proc.stdout.close() 84 | self.proc.kill() 85 | -------------------------------------------------------------------------------- /README-old.md: -------------------------------------------------------------------------------- 1 | # F# Language Support for Open Editors 2 | 3 | [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/fsharp/fsharpbinding?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | 5 | This project contains advanced editing support for F# for a number of open editors. It is made up of the following projects: 6 | * [F# mode for Emacs](emacs/README.md) 7 | * [F# mode for Vim](vim/README.mkd) 8 | * [F# mode for Sublime Text](sublimetext/README.md) 9 | * [F# mode for Atom](https://github.com/fsprojects/FSharp.Atom) 10 | * [FSharp.AutoComplete](FSharp.AutoComplete/README.md) 11 | * An old copy of the F# addin for MonoDevelop and Xamarin Studio 5.9. The latest development branch of this code is now hosted at [FSharpMDXS](https://github.com/fsharp/FSharpMDXS) 12 | 13 | 14 | If you are interested in adding rich editor support for another editor, please open an [issue](https://github.com/fsharp/fsharpbinding/issues) to kick-start the discussion. 15 | 16 | See the [F# Cross-Platform Development Guide](http://fsharp.org/guides/mac-linux-cross-platform/index.html#editing) for F# with Sublime Text 2, Vim and other editors not covered here. 17 | 18 | ## Build Status 19 | 20 | The CI builds are handled by a [FAKE script](FSharp.AutoComplete/build.fsx), which: 21 | 22 | * Builds FSharp.AutoComplete 23 | * Runs FSharp.AutoComplete unit tests 24 | * Runs FSharp.AutoComplete integration tests 25 | * Runs Emacs unit tests 26 | * Runs Emacs integration tests 27 | * Runs Emacs byte compilation 28 | 29 | ### Travis [![Travis build status](https://travis-ci.org/fsharp/fsharpbinding.png)](https://travis-ci.org/fsharp/fsharpbinding) 30 | 31 | See [.travis.yml](.travis.yml) for details. 32 | 33 | ### AppVeyor [![AppVeyor build status](https://ci.appveyor.com/api/projects/status/y1s7nje31qi1j8ed)](https://ci.appveyor.com/project/fsgit/fsharpbinding) 34 | 35 | The configuration is contained in [appveyor.yml](appveyor.yml). Currently the emacs integration tests do not run successfully on AppVeyor and are excluded by the FAKE script. 36 | 37 | ## Building, using and contributing 38 | 39 | See the README for each individual component: 40 | 41 | * [fsautocomplete](FSharp.AutoComplete/README.md) 42 | * [emacs](emacs/README.md) 43 | * [vim](vim/README.mkd) 44 | * [Sublime Text](sublimetext/README.md) 45 | 46 | ## Shared Components 47 | 48 | The core shared component is FSharp.Compiler.Service.dll from the 49 | community [FSharp.Compiler.Service](https://github.com/fsharp/FSharp.Compiler.Service) project. 50 | This is used by both [fsautocomplete.exe](https://github.com/fsharp/fsharpbinding/tree/master/FSharp.AutoComplete), 51 | a command-line utility to sit behind Emacs, Vim and other editing environments components. 52 | 53 | For more information about F# see [The F# Software Foundation](http://fsharp.org). Join [The F# Open Source Group](http://fsharp.github.io). We use [github](https://github.com/fsharp/fsharpbinding) for tracking work items and suggestions. 54 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/FSharp.AutoComplete.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30501.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.CompilerBinding", "..\FSharp.CompilerBinding\FSharp.CompilerBinding.fsproj", "{88F6940F-D300-474C-B2A7-E2ECD5B04B57}" 7 | EndProject 8 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.AutoComplete", "FSharp.AutoComplete.fsproj", "{B6AB4EF3-8F60-41A1-AB0C-851A6DEB169E}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|Mixed Platforms = Debug|Mixed Platforms 14 | Debug|x86 = Debug|x86 15 | Release|Any CPU = Release|Any CPU 16 | Release|Mixed Platforms = Release|Mixed Platforms 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {88F6940F-D300-474C-B2A7-E2ECD5B04B57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {88F6940F-D300-474C-B2A7-E2ECD5B04B57}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {88F6940F-D300-474C-B2A7-E2ECD5B04B57}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 23 | {88F6940F-D300-474C-B2A7-E2ECD5B04B57}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 24 | {88F6940F-D300-474C-B2A7-E2ECD5B04B57}.Debug|x86.ActiveCfg = Debug|Any CPU 25 | {88F6940F-D300-474C-B2A7-E2ECD5B04B57}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {88F6940F-D300-474C-B2A7-E2ECD5B04B57}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {88F6940F-D300-474C-B2A7-E2ECD5B04B57}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 28 | {88F6940F-D300-474C-B2A7-E2ECD5B04B57}.Release|Mixed Platforms.Build.0 = Release|Any CPU 29 | {88F6940F-D300-474C-B2A7-E2ECD5B04B57}.Release|x86.ActiveCfg = Release|Any CPU 30 | {B6AB4EF3-8F60-41A1-AB0C-851A6DEB169E}.Debug|Any CPU.ActiveCfg = Debug|x86 31 | {B6AB4EF3-8F60-41A1-AB0C-851A6DEB169E}.Debug|Any CPU.Build.0 = Debug|x86 32 | {B6AB4EF3-8F60-41A1-AB0C-851A6DEB169E}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 33 | {B6AB4EF3-8F60-41A1-AB0C-851A6DEB169E}.Debug|Mixed Platforms.Build.0 = Debug|x86 34 | {B6AB4EF3-8F60-41A1-AB0C-851A6DEB169E}.Debug|x86.ActiveCfg = Debug|x86 35 | {B6AB4EF3-8F60-41A1-AB0C-851A6DEB169E}.Debug|x86.Build.0 = Debug|x86 36 | {B6AB4EF3-8F60-41A1-AB0C-851A6DEB169E}.Release|Any CPU.ActiveCfg = Release|x86 37 | {B6AB4EF3-8F60-41A1-AB0C-851A6DEB169E}.Release|Any CPU.Build.0 = Release|x86 38 | {B6AB4EF3-8F60-41A1-AB0C-851A6DEB169E}.Release|Mixed Platforms.ActiveCfg = Release|x86 39 | {B6AB4EF3-8F60-41A1-AB0C-851A6DEB169E}.Release|Mixed Platforms.Build.0 = Release|x86 40 | {B6AB4EF3-8F60-41A1-AB0C-851A6DEB169E}.Release|x86.ActiveCfg = Release|x86 41 | {B6AB4EF3-8F60-41A1-AB0C-851A6DEB169E}.Release|x86.Build.0 = Release|x86 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | GlobalSection(MonoDevelopProperties) = preSolution 47 | StartupItem = FSharp.AutoComplete.fsproj 48 | EndGlobalSection 49 | EndGlobal 50 | -------------------------------------------------------------------------------- /sublimetext/FSharp/lib/editor.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | import sublime 6 | 7 | import logging 8 | import os 9 | 10 | from FSharp.fsac import server 11 | from FSharp.fsac.client import FsacClient 12 | from FSharp.fsac.request import CompilerLocationRequest 13 | from FSharp.fsac.request import ProjectRequest 14 | from FSharp.fsac.request import ParseRequest 15 | from FSharp.lib.project import FSharpFile 16 | from FSharp.lib.project import FSharpProjectFile 17 | from FSharp.lib import response_processor 18 | from FSharp.lib.response_processor import ON_COMPILER_PATH_AVAILABLE 19 | 20 | 21 | _logger = logging.getLogger(__name__) 22 | 23 | 24 | class Editor(object): 25 | """Global editor state. 26 | """ 27 | def __init__(self, resp_proc): 28 | _logger.info ('starting fsac server...') 29 | self.fsac = FsacClient(server.start(), resp_proc) 30 | self.compilers_path = None 31 | self.project_file = None 32 | self.fsac.send_request (CompilerLocationRequest()) 33 | response_processor.add_listener(ON_COMPILER_PATH_AVAILABLE, 34 | self.on_compiler_path_available) 35 | 36 | def on_compiler_path_available(self, data): 37 | self.compilers_path = data['response'].compilers_path 38 | 39 | @property 40 | def compiler_path(self): 41 | if self.compilers_path is None: 42 | return None 43 | return os.path.join(self.compilers_path, 'fsc.exe') 44 | 45 | @property 46 | def interpreter_path(self): 47 | if self.compilers_path is None: 48 | return None 49 | return os.path.join(self.compilers_path, 'fsi.exe') 50 | 51 | def refresh(self, fs_file): 52 | assert isinstance(fs_file, FSharpFile), 'wrong argument: %s' % fs_file 53 | # todo: run in alternate thread 54 | 55 | if not self.project_file: 56 | self.project_file = FSharpProjectFile.from_path(fs_file.path) 57 | self.set_project() 58 | return 59 | 60 | if not self.project_file.governs(fs_file.path): 61 | new_project_file = FSharpProjectFile.from_path(fs_file.path) 62 | self.project_file = new_project_file 63 | self.set_project() 64 | return 65 | 66 | def set_project(self): 67 | self.fsac.send_request(ProjectRequest(self.project_file.path)) 68 | 69 | def parse_file(self, fs_file, content): 70 | self.fsac.send_request(ParseRequest(fs_file.path, content)) 71 | 72 | def parse_view(self, view): 73 | # todo: what about unsaved files? 74 | fs_file = FSharpFile(view) 75 | if not fs_file.is_fsharp_file: 76 | return 77 | self.refresh(fs_file) 78 | # todo: very inneficient 79 | if fs_file.is_code: 80 | content = view.substr(sublime.Region (0, view.size())) 81 | self.parse_file(fs_file, content) 82 | 83 | -------------------------------------------------------------------------------- /sublimetext/FSharp/fsac/response.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | import sublime 6 | 7 | 8 | class CompilerLocationResponse (object): 9 | def __init__(self, content): 10 | self.content = content 11 | 12 | @property 13 | def compilers_path(self): 14 | return self.content['Data'] 15 | 16 | 17 | class ProjectResponse (object): 18 | def __init__(self, content): 19 | self.content = content 20 | 21 | @property 22 | def files(self): 23 | return self.content['Data']['Files'] 24 | 25 | @property 26 | def framework(self): 27 | return self.content ['Data']['Framework'] 28 | 29 | @property 30 | def output(self): 31 | return self.content ['Data']['Output'] 32 | 33 | @property 34 | def output(self): 35 | return self.content ['Data']['References'] 36 | 37 | 38 | class TopLevelDeclaration(object): 39 | def __init__(self, data): 40 | self.data = data 41 | 42 | @property 43 | def first_location(self): 44 | col = self.data['BodyRange']['Item1']['Column'] 45 | row = self.data['BodyRange']['Item1']['Line'] 46 | return (row - 1, col) 47 | 48 | @property 49 | def name(self): 50 | return self.data['Name'] 51 | 52 | def __str__(self): 53 | return 'Declaration({0})<{1},{2}>'.format(self.name, *self.first_location) 54 | 55 | def to_menu_data(self): 56 | return [self.name, 'fs_go_to_location', {'loc': list(self.first_location)}] 57 | 58 | 59 | class DeclarationsResponse(object): 60 | def __init__(self, data): 61 | self.data = data 62 | 63 | @property 64 | def declarations(self): 65 | for decl in self.data['Data'][0]['Nested']: 66 | yield TopLevelDeclaration (decl) 67 | 68 | def __str__(self): 69 | return '' 70 | 71 | 72 | class ErrorInfo(object): 73 | def __init__(self, data): 74 | self.data = data 75 | 76 | @property 77 | def start_line(self): 78 | return self.data['StartLine'] 79 | 80 | @property 81 | def start_line_alternate(self): 82 | return self.data['StartLineAlternate'] 83 | 84 | @property 85 | def end_line(self): 86 | return self.data['EndLine'] 87 | 88 | @property 89 | def end_line_alternate(self): 90 | return self.data['EndLineAlternate'] 91 | 92 | @property 93 | def start_column(self): 94 | return self.data['StartColumn'] 95 | 96 | @property 97 | def end_column(self): 98 | return self.data['EndColumn'] 99 | 100 | @property 101 | def length(self): 102 | return self.end_column - self.start_column 103 | 104 | @property 105 | def severity(self): 106 | return self.data['Severity'] 107 | 108 | @property 109 | def message(self): 110 | return self.data['Message'] 111 | 112 | @property 113 | def subcategory(self): 114 | return self.data['Subcategory'] 115 | 116 | @property 117 | def file_name(self): 118 | return self.data['FileName'] 119 | 120 | def to_region(self, view): 121 | row = self.start_line 122 | col = self.start_column 123 | pt = view.text_point(row, col) 124 | return sublime.Region(pt, pt + self.length) -------------------------------------------------------------------------------- /emacs/test/Test1/Test1.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {116cc2f9-f987-4b3d-915a-34cac04a73da} 9 | Exe 10 | Test1 11 | Test1 12 | Test1 13 | False 14 | 15 | 16 | Program.fs 17 | 18 | 19 | 4.3.0.0 20 | 11 21 | 22 | 23 | True 24 | full 25 | False 26 | False 27 | bin\Debug\ 28 | DEBUG;TRACE 29 | 3 30 | x86 31 | bin\Debug\Test1.XML 32 | 33 | 34 | pdbonly 35 | True 36 | True 37 | bin\Release\ 38 | TRACE 39 | 3 40 | x86 41 | bin\Release\Test1.XML 42 | False 43 | 44 | 45 | 46 | True 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets 60 | 61 | 62 | 63 | 64 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets 65 | 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /emacs/test/fsharp-doc-tests.el: -------------------------------------------------------------------------------- 1 | (require 'test-common) 2 | 3 | ;;; Test data 4 | 5 | (defconst val-tooltip 6 | "val id : x:'a -> b 7 | 8 | Full name: Modid.id") 9 | 10 | 11 | (defconst property-tooltip 12 | "property id : a 13 | 14 | Full name: Modid.id") 15 | 16 | 17 | (defconst type-tooltip 18 | "type id = string 19 | 20 | Full name: Modid.id") 21 | 22 | 23 | (defconst object-tooltip 24 | "Multiple items 25 | type id = 26 | new : unit -> Has 27 | static member All : ConstraintExpression 28 | static member Attribute<'T> : unit -> ResolvableConstraintExpression + 1 overload 29 | static member Count : ResolvableConstraintExpression 30 | static member Exactly : expectedCount:int -> ConstraintExpression 31 | static member InnerException : ResolvableConstraintExpression 32 | static member Length : ResolvableConstraintExpression 33 | static member Member : expected:obj -> CollectionContainsConstraint 34 | static member Message : ResolvableConstraintExpression 35 | static member No : ConstraintExpression 36 | ... 37 | 38 | Full name: Modid.id 39 | ") 40 | 41 | ;;; ---------------------------------------------------------------------------- 42 | ;;; Tests 43 | 44 | (defun parse-into-lines (str) 45 | (split-string (fsharp-doc/format-for-minibuffer str) "[\n\r]")) 46 | 47 | ;;; Vals 48 | 49 | (check "parsed val should be a single line" 50 | (let ((lines (parse-into-lines val-tooltip))) 51 | (should (= 1 (length lines))))) 52 | 53 | (check "parsed val should start with 'val'" 54 | (should-match "^val" (fsharp-doc/format-for-minibuffer val-tooltip))) 55 | 56 | (check "parsed val should contain type signature" 57 | (should-match ": x:'a -> b$" (fsharp-doc/format-for-minibuffer val-tooltip))) 58 | 59 | (check "parsed val should not be module-qualified" 60 | (should-match "^val id" (fsharp-doc/format-for-minibuffer val-tooltip))) 61 | 62 | ;;; Types 63 | 64 | (check "parsed type should be a single line" 65 | (let ((lines (parse-into-lines type-tooltip))) 66 | (should (= 1 (length lines))))) 67 | 68 | (check "parsed type should start with 'type'" 69 | (should-match "^type" (fsharp-doc/format-for-minibuffer type-tooltip))) 70 | 71 | (check "type identifier should be module-qualified" 72 | (should-match "^type Modid.id" (fsharp-doc/format-for-minibuffer type-tooltip))) 73 | 74 | ;;; Properties 75 | 76 | (check "parsed property should be a single line" 77 | (let ((lines (parse-into-lines property-tooltip))) 78 | (should (= 1 (length lines))))) 79 | 80 | (check "parsed property should start with 'property'" 81 | (should-match "^property" (fsharp-doc/format-for-minibuffer property-tooltip))) 82 | 83 | (check "parsed property should end with type" 84 | (should-match ": a$" (fsharp-doc/format-for-minibuffer property-tooltip))) 85 | 86 | (check "property identifier should be qualified" 87 | (should-match "^property Modid.id" (fsharp-doc/format-for-minibuffer property-tooltip))) 88 | 89 | ;;; Objects 90 | 91 | (check "parsed object should be a single line" 92 | (let ((lines (parse-into-lines object-tooltip))) 93 | (should (= 1 (length lines))))) 94 | 95 | (check "parsed object should start with 'type'" 96 | (should-match "^type" (fsharp-doc/format-for-minibuffer object-tooltip))) 97 | 98 | (check "parsed object should be fully qualified" 99 | (should-match "^type Modid.id" (fsharp-doc/format-for-minibuffer object-tooltip))) 100 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/Test1/Test1.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {116cc2f9-f987-4b3d-915a-34cac04a73da} 9 | Exe 10 | Test1 11 | Test1 12 | Test1 13 | False 14 | 15 | 16 | Program.fs 17 | 18 | 19 | 4.3.0.0 20 | 11 21 | 22 | 23 | True 24 | full 25 | False 26 | False 27 | bin\Debug\ 28 | DEBUG;TRACE 29 | 3 30 | x86 31 | bin\Debug\Test1.XML 32 | 33 | 34 | pdbonly 35 | True 36 | True 37 | bin\Release\ 38 | TRACE 39 | 3 40 | x86 41 | bin\Release\Test1.XML 42 | False 43 | 44 | 45 | 46 | True 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets 60 | 61 | 62 | 63 | 64 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets 65 | 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/ErrorTests/Test1.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {116cc2f9-f987-4b3d-915a-34cac04a73da} 9 | Exe 10 | Test1 11 | Test1 12 | Test1 13 | False 14 | 15 | 16 | Program.fs 17 | 18 | 19 | 4.3.0.0 20 | 11 21 | 22 | 23 | True 24 | full 25 | False 26 | False 27 | bin\Debug\ 28 | DEBUG;TRACE 29 | 3 30 | x86 31 | bin\Debug\Test1.XML 32 | 33 | 34 | pdbonly 35 | True 36 | True 37 | bin\Release\ 38 | TRACE 39 | 3 40 | x86 41 | bin\Release\Test1.XML 42 | False 43 | 44 | 45 | 46 | True 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets 60 | 61 | 62 | 63 | 64 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets 65 | 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/MultiProj/Proj1/Proj1.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {116cc2f9-f987-4b3d-915a-34cac04a73da} 9 | Exe 10 | Proj1 11 | Proj1 12 | Proj1 13 | False 14 | 15 | 16 | Program.fs 17 | 18 | 19 | 4.3.0.0 20 | 11 21 | 22 | 23 | True 24 | full 25 | False 26 | False 27 | bin\Debug\ 28 | DEBUG;TRACE 29 | 3 30 | x86 31 | bin\Debug\Proj.XML 32 | 33 | 34 | pdbonly 35 | True 36 | True 37 | bin\Release\ 38 | TRACE 39 | 3 40 | x86 41 | bin\Release\Proj1.XML 42 | False 43 | 44 | 45 | 46 | True 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets 60 | 61 | 62 | 63 | 64 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets 65 | 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/MultiProj/Proj2/Proj2.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {116cc2f9-f987-4b3d-915a-34cac04a73da} 9 | Exe 10 | Proj2 11 | Proj2 12 | Proj2 13 | False 14 | 15 | 16 | Program.fs 17 | 18 | 19 | 4.3.0.0 20 | 11 21 | 22 | 23 | True 24 | full 25 | False 26 | False 27 | bin\Debug\ 28 | DEBUG;TRACE 29 | 3 30 | x86 31 | bin\Debug\Proj.XML 32 | 33 | 34 | pdbonly 35 | True 36 | True 37 | bin\Release\ 38 | TRACE 39 | 3 40 | x86 41 | bin\Release\Proj2.XML 42 | False 43 | 44 | 45 | 46 | True 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets 60 | 61 | 62 | 63 | 64 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets 65 | 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/Test1Json/Test1.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {116cc2f9-f987-4b3d-915a-34cac04a73da} 9 | Exe 10 | Test1 11 | Test1 12 | Test1 13 | False 14 | 15 | 16 | Program.fs 17 | 18 | 19 | 4.3.0.0 20 | 11 21 | 22 | 23 | True 24 | full 25 | False 26 | False 27 | bin\Debug\ 28 | DEBUG;TRACE 29 | 3 30 | x86 31 | bin\Debug\Test1.XML 32 | 33 | 34 | pdbonly 35 | True 36 | True 37 | bin\Release\ 38 | TRACE 39 | 3 40 | x86 41 | bin\Release\Test1.XML 42 | False 43 | 44 | 45 | 46 | True 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets 60 | 61 | 62 | 63 | 64 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets 65 | 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/ErrorTestsJson/Test1.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {116cc2f9-f987-4b3d-915a-34cac04a73da} 9 | Exe 10 | Test1 11 | Test1 12 | Test1 13 | False 14 | 15 | 16 | Program.fs 17 | 18 | 19 | 4.3.0.0 20 | 11 21 | 22 | 23 | True 24 | full 25 | False 26 | False 27 | bin\Debug\ 28 | DEBUG;TRACE 29 | 3 30 | x86 31 | bin\Debug\Test1.XML 32 | 33 | 34 | pdbonly 35 | True 36 | True 37 | bin\Release\ 38 | TRACE 39 | 3 40 | x86 41 | bin\Release\Test1.XML 42 | False 43 | 44 | 45 | 46 | True 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets 60 | 61 | 62 | 63 | 64 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets 65 | 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/FindDeclarations/FindDecl.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {116cc2f9-f987-4b3d-915a-34cac04a73da} 9 | Exe 10 | Test1 11 | Test1 12 | Test1 13 | False 14 | 15 | 16 | Program.fs 17 | 18 | 19 | 4.3.0.0 20 | 11 21 | 22 | 23 | True 24 | full 25 | False 26 | False 27 | bin\Debug\ 28 | DEBUG;TRACE 29 | 3 30 | x86 31 | bin\Debug\Test1.XML 32 | 33 | 34 | pdbonly 35 | True 36 | True 37 | bin\Release\ 38 | TRACE 39 | 3 40 | x86 41 | bin\Release\Test1.XML 42 | False 43 | 44 | 45 | 46 | True 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets 60 | 61 | 62 | 63 | 64 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets 65 | 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/test/integration/RobustCommands/Project/Test1.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {116cc2f9-f987-4b3d-915a-34cac04a73da} 9 | Exe 10 | Test1 11 | Test1 12 | Test1 13 | False 14 | 15 | 16 | Program.fs 17 | 18 | 19 | 4.3.0.0 20 | 11 21 | 22 | 23 | True 24 | full 25 | False 26 | False 27 | bin\Debug\ 28 | DEBUG;TRACE 29 | 3 30 | x86 31 | bin\Debug\Test1.XML 32 | 33 | 34 | pdbonly 35 | True 36 | True 37 | bin\Release\ 38 | TRACE 39 | 3 40 | x86 41 | bin\Release\Test1.XML 42 | False 43 | 44 | 45 | 46 | True 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets 60 | 61 | 62 | 63 | 64 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets 65 | 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /emacs/Makefile: -------------------------------------------------------------------------------- 1 | # Directories 2 | 3 | base_d = $(abspath ..) 4 | test_d = $(abspath test) 5 | tmp_d = $(abspath tmp) 6 | bin_d = $(abspath bin) 7 | 8 | # Elisp files required for tests. 9 | src_files = $(wildcard ./*.el) 10 | obj_files = $(patsubst %.el,%.elc,$(src_files)) 11 | integration_tests = $(test_d)/integration-tests.el 12 | unit_tests = $(filter-out $(integration_tests), $(wildcard $(test_d)/*tests.el)) 13 | utils = $(test_d)/test-common.el 14 | 15 | # Emacs command format. 16 | emacs = emacs 17 | load_files = $(patsubst %,-l %, $(utils)) 18 | load_unit_tests = $(patsubst %,-l %, $(unit_tests)) 19 | load_integration_tests = $(patsubst %,-l %, $(integration_tests)) 20 | 21 | # HACK: Vars for manually building the ac binary. 22 | # We should be really able to use the top-level makefile for this... 23 | ac_exe = $(bin_d)/fsautocomplete.exe 24 | ac_fsproj = $(base_d)/FSharp.AutoComplete/FSharp.AutoComplete.fsproj 25 | ac_out = $(base_d)/FSharp.AutoComplete/bin/Debug/ 26 | 27 | # Installation paths. 28 | dest_root = $(HOME)/.emacs.d/fsharp-mode/ 29 | dest_bin = $(HOME)/.emacs.d/fsharp-mode/bin/ 30 | 31 | # ---------------------------------------------------------------------------- 32 | 33 | .PHONY : test unit-test integration-test packages clean-elc install byte-compile check-compile run 34 | 35 | # Building 36 | 37 | $(ac_exe) : $(bin_d) ~/.config/.mono/certs 38 | xbuild $(ac_fsproj) /property:OutputPath="$(bin_d)" 39 | 40 | ~/.config/.mono/certs: 41 | mozroots --import --sync --quiet 42 | 43 | install : $(ac_exe) $(dest_root) $(dest_bin) 44 | # Install elisp packages 45 | $(emacs) $(load_files) --batch -f load-packages 46 | # Copy files 47 | for f in $(src_files); do \ 48 | cp $$f $(dest_root) ;\ 49 | done 50 | # Copy bin folder. 51 | cp -R $(bin_d) $(dest_root) 52 | 53 | 54 | $(dest_root) :; mkdir -p $(dest_root) 55 | $(dest_bin) :; mkdir -p $(dest_bin) 56 | $(bin_d) :; mkdir -p $(bin_d) 57 | 58 | # Cleaning 59 | 60 | clean : clean-elc 61 | rm -rf $(bin_d) 62 | rm -rf $(tmp_d) 63 | 64 | clean-elc : 65 | rm -f *.elc 66 | rm -f $(test_d)/*.elc 67 | 68 | # Testing 69 | 70 | test unit-test : 71 | HOME=$(tmp_d) ;\ 72 | $(emacs) $(load_files) --batch -f run-fsharp-unit-tests 73 | 74 | integration-test : $(ac_exe) packages 75 | HOME=$(tmp_d) ;\ 76 | $(emacs) $(load_files) --batch -f run-fsharp-integration-tests 77 | 78 | test-all : unit-test integration-test check-compile check-declares 79 | 80 | packages : 81 | HOME=$(tmp_d) ;\ 82 | $(emacs) $(load_files) --batch -f load-packages 83 | 84 | byte-compile : packages 85 | HOME=$(tmp_d) ;\ 86 | $(emacs) -batch --eval "(package-initialize)"\ 87 | --eval "(add-to-list 'load-path \"$(base_d)/emacs\")" \ 88 | -f batch-byte-compile $(src_files) 89 | 90 | check-declares : packages 91 | HOME=$(tmp_d) ;\ 92 | $(emacs) -batch --eval "(package-initialize)"\ 93 | --eval '(when (check-declare-directory "$(base_d)/emacs") (kill-emacs 1)))' 94 | 95 | check-compile : packages $(obj_files) 96 | 97 | .el.elc: 98 | HOME=$(tmp_d) ;\ 99 | $(emacs) -batch --eval "(package-initialize)"\ 100 | --eval "(add-to-list 'load-path \"$(base_d)/emacs\")" \ 101 | --eval '(setq byte-compile-error-on-warn t)' \ 102 | -f batch-byte-compile $< 103 | 104 | run : $(ac_exe) packages 105 | HOME=$(tmp_d) ;\ 106 | $(emacs) $(load_files) -f configure-fsharp-tests 107 | -------------------------------------------------------------------------------- /emacs/test/Test2/Test2.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {116cc2f9-f987-4b3d-915a-34cac04a73db} 9 | Library 10 | Test2 11 | Test2 12 | Test2 13 | False 14 | 15 | 16 | Program.fs 17 | 18 | 19 | 4.3.0.0 20 | 11 21 | 22 | 23 | True 24 | full 25 | False 26 | False 27 | bin\Debug\ 28 | DEBUG;TRACE 29 | 3 30 | x86 31 | bin\Debug\Test2.XML 32 | 33 | 34 | pdbonly 35 | True 36 | True 37 | bin\Release\ 38 | TRACE 39 | 3 40 | x86 41 | bin\Release\Test2.XML 42 | False 43 | 44 | 45 | 46 | True 47 | 48 | 49 | 50 | 51 | 52 | {116cc2f9-f987-4b3d-915a-34cac04a73da} 53 | Test1 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets 63 | 64 | 65 | 66 | 67 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets 68 | 69 | 70 | 71 | 72 | 79 | 80 | -------------------------------------------------------------------------------- /sublimetext/FSharp/sublime_plugin_lib/panels.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | import sublime 6 | 7 | import os 8 | 9 | from .sublime import after 10 | 11 | 12 | class OutputPanel(object): 13 | """Manages an ST output panel. 14 | 15 | Can be used as a file-like object. 16 | """ 17 | 18 | def __init__(self, name, 19 | base_dir=None, 20 | syntax='Packages/Text/Plain text.tmLanguage', 21 | **kwargs): 22 | """ 23 | @name 24 | This panel's name. 25 | @base_dir 26 | Directory used to look files matched by regular expressions. 27 | @syntax: 28 | This panel's syntax. 29 | @kwargs 30 | Any number of settings to set in the underlying view via `.set()`. 31 | 32 | Common settings: 33 | - result_file_regex 34 | - result_line_regex 35 | - word_wrap 36 | - line_numbers 37 | - gutter 38 | - scroll_past_end 39 | """ 40 | 41 | self.name = name 42 | self.window = sublime.active_window() 43 | 44 | if not hasattr(self, 'view'): 45 | # Try not to call get_output_panel until the regexes are assigned 46 | self.view = self.window.create_output_panel(self.name) 47 | 48 | # Default to the current file directory 49 | if (not base_dir and 50 | self.window.active_view() and 51 | self.window.active_view().file_name()): 52 | base_dir = os.path.dirname(self.window.active_view().file_name()) 53 | 54 | self.set('result_base_dir', base_dir) 55 | self.set('syntax', syntax) 56 | 57 | self.set('result_file_regex', '') 58 | self.set('result_line_regex', '') 59 | self.set('word_wrap', False) 60 | self.set('line_numbers', False) 61 | self.set('gutter', False) 62 | self.set('scroll_past_end', False) 63 | 64 | def set(self, name, value): 65 | self.view.settings().set(name, value) 66 | 67 | def _clean_text(self, text): 68 | return text.replace('\r', '') 69 | 70 | def write(self, text): 71 | assert isinstance(text, str), 'must pass decoded text data' 72 | text = self._clean_text(text) 73 | fun = lambda: self.view.run_command('append', {'characters': text, 'force': True, 'scroll_to_end': True}) 74 | after(0, fun) 75 | 76 | def flush(self): 77 | pass 78 | 79 | def show(self): 80 | # Call create_output_panel a second time after assigning the above 81 | # settings, so that it'll be picked up as a result buffer 82 | self.window.create_output_panel(self.name) 83 | self.window.run_command('show_panel', { 84 | 'panel': 'output.' + self.name}) 85 | 86 | def close(self): 87 | pass 88 | 89 | 90 | class ErrorPanel(object): 91 | def __init__(self): 92 | self.panel = OutputPanel('dart.info') 93 | self.panel.write('=' * 80) 94 | self.panel.write('\n') 95 | self.panel.write("Dart - Something's not quite right\n") 96 | self.panel.write('=' * 80) 97 | self.panel.write('\n') 98 | self.panel.write('\n') 99 | 100 | def write(self, text): 101 | self.panel.write(text) 102 | 103 | def show(self): 104 | self.panel.show() 105 | -------------------------------------------------------------------------------- /vim/ftplugin/fsi.py: -------------------------------------------------------------------------------- 1 | from subprocess import Popen, PIPE 2 | from os import path 3 | import string 4 | import threading 5 | import tempfile 6 | import Queue 7 | import uuid 8 | import hidewin 9 | 10 | class FSharpInteractive: 11 | def __init__(self, fsi_path, is_debug = False): 12 | self._debug = is_debug 13 | #self.logfiledir = tempfile.gettempdir() + "/log.txt" 14 | #self.logfile = open(self.logfiledir, "w") 15 | id = 'vim-' + str(uuid.uuid4()) 16 | command = [fsi_path, '--fsi-server:%s' % id, '--nologo'] 17 | opts = { 'stdin': PIPE, 'stdout': PIPE, 'stderr': PIPE, 'shell': False, 'universal_newlines': True } 18 | hidewin.addopt(opts) 19 | self.p = Popen(command, **opts) 20 | 21 | if is_debug: 22 | logfiledir = tempfile.gettempdir() + "/fsi-log.txt" 23 | self.logfile = open(logfiledir, "w") 24 | 25 | self._should_work = True 26 | self.lines = Queue.Queue() 27 | self.worker = threading.Thread(target=self._work, args=[]) 28 | self.worker.daemon = True 29 | self.worker.start() 30 | self.err_worker = threading.Thread(target=self._err_work, args=[]) 31 | self.err_worker.daemon = True 32 | self.err_worker.start() 33 | x = self.purge() 34 | self._current_path = None 35 | 36 | def _log(self, msg): 37 | if self._debug: 38 | self.logfile.write(msg + "\n") 39 | self.logfile.flush() 40 | 41 | def shutdown(self): 42 | print "shutting down fsi" 43 | self._should_work = False 44 | self.p.kill() 45 | 46 | def set_loc(self, path, line_num): 47 | self.p.stdin.write("#" + str(line_num) + " @\"" + path + "\"\n") 48 | 49 | def send(self, txt): 50 | self.p.stdin.write(txt + "\n") 51 | self.p.stdin.write(";;\n") 52 | self._log(">" + txt + ";;") 53 | 54 | def cd(self, path): 55 | if self._current_path == path: 56 | return 57 | self.p.stdin.write("System.IO.Directory.SetCurrentDirectory(@\"" + path + "\");;\n") 58 | self.p.stdin.write("#silentCd @\"" + path + "\";;\n") 59 | self.purge() 60 | self._current_path = path 61 | 62 | def purge(self): 63 | items = [] 64 | while(True): 65 | try: 66 | l = self.lines.get(False).rstrip() 67 | if 'SERVER-PROMPT>' not in l: 68 | items.append(l) 69 | except: 70 | break 71 | return items 72 | 73 | def read_until_prompt(self, time_out): 74 | output = [] 75 | try: 76 | l = self.lines.get(True, time_out) 77 | if 'SERVER-PROMPT>' in l: 78 | return output 79 | output.append(str(l).rstrip()) 80 | while(True): 81 | l = self.read_one() 82 | if 'SERVER-PROMPT>' in l: 83 | return output 84 | output.append(str(l).rstrip()) 85 | return output 86 | except Exception as ex: 87 | output.append(".....") #indicate that there may be more lines of output 88 | return output 89 | 90 | def read_one(self): 91 | return self.lines.get(True, 0.5) 92 | 93 | def _work(self): 94 | while(self._should_work): 95 | try: 96 | l = self.p.stdout.readline() 97 | self.lines.put(l, True) 98 | self._log(l) 99 | except Exception as ex: 100 | print ex 101 | 102 | def _err_work(self): 103 | while(self._should_work): 104 | l = self.p.stderr.readline() 105 | self.lines.put(l, True) 106 | self._log( "err: " + l) 107 | -------------------------------------------------------------------------------- /sublimetext/FSharp/fsac/request.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | 6 | class Request (object): 7 | def __init__(self, timeout=250, add_newline=True): 8 | self.add_newline = add_newline 9 | self.timeout = timeout 10 | 11 | def encode(self): 12 | data = str(self) 13 | if self.add_newline: 14 | data += '\n' 15 | return data.encode ('utf-8') 16 | 17 | 18 | class CompilerLocationRequest(Request): 19 | def __init__(self, *args, **kwargs): 20 | super ().__init__ (*args, **kwargs) 21 | 22 | def __str__(self): 23 | return 'compilerlocation' 24 | 25 | 26 | class ProjectRequest(Request): 27 | def __init__(self, project_file, *args, **kwargs): 28 | super ().__init__ (*args, **kwargs) 29 | self.project_file = project_file 30 | 31 | def __str__(self): 32 | return 'project "{0}"'.format(self.project_file) 33 | 34 | 35 | class ParseRequest(Request): 36 | def __init__(self, file_name, content='', full=True, *args, **kwargs): 37 | super ().__init__ (*args, add_newline=False, **kwargs) 38 | self.file_name = file_name 39 | self.content = content 40 | self.full = full 41 | 42 | def __str__(self): 43 | cmd = 'parse "{0}"'.format(self.file_name) 44 | if self.full: 45 | cmd += ' full' 46 | cmd += '\n' 47 | cmd += self.content + '\n<>\n' 48 | return cmd 49 | 50 | 51 | class FindDeclRequest(Request): 52 | def __init__(self, file_name, row, col, *args, **kwargs): 53 | super().__init__ (*args, **kwargs) 54 | self.file_name = file_name 55 | self.row = row 56 | self.col = col 57 | 58 | def __str__(self): 59 | return 'finddecl "{0}" {1} {2} {3}'.format( 60 | self.file_name, 61 | self.row, 62 | self.col, 63 | self.timeout, 64 | ) 65 | 66 | 67 | class CompletionRequest(Request): 68 | def __init__(self, file_name, row, col, *args, **kwargs): 69 | super().__init__ (*args, **kwargs) 70 | self.file_name = file_name 71 | self.row = row 72 | self.col = col 73 | 74 | def __str__(self): 75 | return 'completion "{0}" {1} {2} {3}'.format( 76 | self.file_name, 77 | self.row, 78 | self.col, 79 | self.timeout, 80 | ) 81 | 82 | 83 | class TooltipRequest(Request): 84 | def __init__(self, file_name, row, col, *args, **kwargs): 85 | super().__init__ (*args, **kwargs) 86 | self.file_name = file_name 87 | self.row = row 88 | self.col = col 89 | 90 | def __str__(self): 91 | return 'tooltip "{0}" {1} {2} {3}'.format( 92 | self.file_name, 93 | self.row, 94 | self.col, 95 | self.timeout, 96 | ) 97 | 98 | 99 | class DeclarationsRequest(Request): 100 | def __init__(self, file_name, *args, **kwargs): 101 | super ().__init__ (*args, **kwargs) 102 | self.file_name = file_name 103 | 104 | def __str__(self): 105 | return 'declarations "{0}"'.format(self.file_name) 106 | 107 | 108 | class DataRequest(Request): 109 | def __init__(self, *args, content='', add_newline=False, **kwargs): 110 | super ().__init__ (*args, add_newline=add_newline, **kwargs) 111 | self.content = content 112 | 113 | def __str__(self): 114 | return self.content 115 | 116 | 117 | class AdHocRequest (Request): 118 | def __init__(self, content, *args, **kwargs): 119 | super ().__init__ (*args, **kwargs) 120 | self.content = content 121 | 122 | def __str__(self): 123 | return self.content 124 | 125 | -------------------------------------------------------------------------------- /sublimetext/FSharp/xevents.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | import logging 6 | 7 | from collections import defaultdict 8 | import json 9 | import sublime 10 | import sublime_plugin 11 | import threading 12 | 13 | from FSharp.fsac.server import completions_queue 14 | from FSharp.fsharp import editor_context 15 | from FSharp.lib.project import FSharpFile 16 | from FSharp.lib.response_processor import add_listener 17 | from FSharp.lib.response_processor import ON_COMPLETIONS_REQUESTED 18 | from FSharp.sublime_plugin_lib.context import ContextProviderMixin 19 | from FSharp.sublime_plugin_lib.sublime import after 20 | 21 | 22 | _logger = logging.getLogger(__name__) 23 | 24 | 25 | class ProjectTracker (sublime_plugin.EventListener): 26 | '''Tracks events. 27 | ''' 28 | edits = defaultdict(int) 29 | edits_lock = threading.Lock() 30 | parsed = {} 31 | parsed_lock = threading.Lock() 32 | 33 | def add_edit(self, view): 34 | with ProjectTracker.edits_lock: 35 | view_id = view.file_name() or view.id() 36 | self.edits[view_id] += 1 37 | after(1500, lambda: self.subtract_edit(view)) 38 | 39 | def subtract_edit(self, view): 40 | with ProjectTracker.edits_lock: 41 | view_id = view.file_name() or view.id() 42 | self.edits[view_id] -= 1 43 | if self.edits[view_id] == 0: 44 | self.on_idle(view) 45 | 46 | def on_activated_async(self, view): 47 | if not FSharpFile(view).is_code_file: 48 | return 49 | _logger.debug ('activated file: %s', view.file_name()) 50 | 51 | with ProjectTracker.parsed_lock: 52 | view_id = view.file_name() or view.id() 53 | if ProjectTracker.parsed.get(view_id): 54 | return 55 | 56 | editor_context.parse_view(view) 57 | self.set_parsed(view, True) 58 | 59 | def on_load_async(self, view): 60 | self.on_activated_async(view) 61 | 62 | def set_parsed(self, view, value): 63 | with ProjectTracker.parsed_lock: 64 | view_id = view.file_name() or view.id() 65 | ProjectTracker.parsed[view_id] = value 66 | 67 | def on_idle(self, view): 68 | editor_context.parse_view(view) 69 | self.set_parsed(view, True) 70 | 71 | def on_modified_async(self, view): 72 | _logger.debug('modified file: %s', view.file_name()) 73 | if not FSharpFile(view).is_code_file: 74 | return 75 | self.add_edit(view) 76 | self.set_parsed(view, False) 77 | 78 | 79 | class ContextProvider(sublime_plugin.EventListener, ContextProviderMixin): 80 | '''Implements contexts for .sublime-keymap files. 81 | ''' 82 | def on_query_context(self, view, key, operator, operand, match_all): 83 | if key == 'fs_is_code_file': 84 | value = FSharpFile(view).is_code 85 | return self._check(value, operator, operand, match_all) 86 | 87 | 88 | class FSharpAutocomplete(sublime_plugin.EventListener): 89 | WAIT_ON_COMPLETIONS = False 90 | 91 | @staticmethod 92 | def on_completions_requested(data): 93 | FSharpAutocomplete.WAIT_ON_COMPLETIONS = True 94 | 95 | def on_query_completions(self, view, prefix, locations): 96 | if not FSharpAutocomplete.WAIT_ON_COMPLETIONS: 97 | return [] 98 | 99 | try: 100 | data = completions_queue.get(block=True, timeout=.75) 101 | data = json.loads(data.decode('utf-8')) 102 | return [[item, item] for item in data['Data']] 103 | except: 104 | return [] 105 | finally: 106 | FSharpAutocomplete.WAIT_ON_COMPLETIONS = False 107 | 108 | 109 | add_listener(ON_COMPLETIONS_REQUESTED, FSharpAutocomplete.on_completions_requested) 110 | -------------------------------------------------------------------------------- /sublimetext/bin/Build.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .DESCRIPTION 3 | Publishes the project locally as a directory. 4 | 5 | .PARAMETER Clean 6 | Whether to erase the target folder's content first. 7 | 8 | .PARAMETER Restart 9 | Whether to restart Sublime Text. 10 | 11 | .PARAMETER Full 12 | Whether to get dependencies too. 13 | #> 14 | [CmdletBinding()] 15 | param([switch]$Clean, 16 | [switch]$Restart, 17 | [switch]$Full) 18 | 19 | 20 | $script:thisDir = split-path $MyInvocation.MyCommand.Path -parent 21 | $script:config = resolve-path (join-path $thisDir "..\plugin_dev.json") -erroraction silentlycontinue 22 | 23 | $msg = @" 24 | You need to set `$global:STPackagesPath to Sublime Text 3's packages path. 25 | 26 | To set global variables in PowerShell: 27 | 28 | PS> `$STPackagesPath = ... 29 | 30 | (Note this is a PowerShell variable, not an environment variable.) 31 | 32 | To obtain Sublime Text's packages path, open Sublime Text, open the Python 33 | console and type in the following: 34 | 35 | sublime.packages_path() 36 | 37 | For more information on Sublime Text's packages path, see: 38 | http://docs.sublimetext.info/en/latest/basic_concepts.html#the-packages-directory 39 | "@ 40 | 41 | if ($config) { 42 | $configData = convertfrom-json "$(get-content $config)" -erroraction silentlycontinue 43 | } 44 | 45 | if ($configData) { 46 | $script:STPackagesPath = $configData.packages_path 47 | if (-not (test-path $script:STPackagesPath)) { 48 | throw "$script:STPackagesPath does not exist" 49 | } 50 | } 51 | 52 | 53 | if (-not (test-path variable:\STPackagesPath) -or 54 | ($global:STPackagesPath -eq $null) -or 55 | -not (test-path $global:STPackagesPath)) { 56 | if (-not $configData) { 57 | throw $msg 58 | exit 1 59 | } 60 | } 61 | 62 | if (-not $script:STPackagesPath) { 63 | $script:STPackagesPath = $global:STPackagesPath 64 | } 65 | 66 | if ($Full) { 67 | push-location $thisDir 68 | & .\GetDependencies.ps1 69 | pop-location 70 | } 71 | 72 | # Check that we don't have both FSharp.sublime-package and FSharp at the same time. 73 | # This may cause conflicts. 74 | write-verbose 'checking installed packages...' 75 | $STInstalledPackagesPath = (resolve-path (join-path $script:STPackagesPath "..\Installed Packages")) 76 | $package = get-item "$STInstalledPackagesPath\FSharp.sublime-package" -erroraction silentlycontinue 77 | 78 | if ($package) { 79 | throw "you can't have .../Installed Packages/FSharp.sublime-package and .../Packages/FSharp at the same time" 80 | } 81 | 82 | write-debug "path to Sublime Text 3 packages is: '$script:STPackagesPath'" 83 | 84 | if ($Restart) { 85 | try { 86 | write-verbose "stopping Sublime Text..." 87 | get-process "sublime_text" -erroraction silentlycontinue | stop-process -erroraction silentlycontinue 88 | start-sleep -milliseconds 250 89 | } 90 | catch [Exception] { 91 | write-debug "error occurred while stopping sublime text" 92 | # ignore 93 | } 94 | } 95 | 96 | $fsharpPackageDir = "$script:STPackagesPath\FSharp" 97 | write-debug "target path is: $fsharpPackageDir" 98 | write-verbose "creating '$fsharpPackageDir' directory..." 99 | [void] (new-item -itemtype 'directory' $fsharpPackageDir -force -erroraction stop) 100 | 101 | if ($Clean) { 102 | write-verbose "erasing content of '$fsharpPackageDir'..." 103 | [void] (remove-item "$fsharpPackageDir/*" -recurse -force -erroraction stop) 104 | } 105 | 106 | # after st has been closed; resources should have been released now 107 | push-location "$thisDir/../FSharp" 108 | write-debug "source directory is: $(get-location)" 109 | write-verbose "copying files from $(get-location) to '$fsharpPackageDir'..." 110 | copy-item * $fsharpPackageDir -force -recurse -erroraction stop 111 | pop-location 112 | 113 | if ($Restart) { 114 | write-verbose "restarting Sublime Text..." 115 | write-debug "path to Sublime Text 3 executable is: $((get-command sublime_text).path)" 116 | sublime_text 117 | } 118 | 119 | write-verbose 'done' -------------------------------------------------------------------------------- /sublimetext/FSharp/lib/response_processor.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | import json 6 | import logging 7 | import os 8 | import queue 9 | 10 | import sublime 11 | import sublime_plugin 12 | 13 | from FSharp.fsac.response import CompilerLocationResponse 14 | from FSharp.fsac.response import DeclarationsResponse 15 | from FSharp.fsac.response import ProjectResponse 16 | from FSharp.fsac.response import ErrorInfo 17 | from FSharp.sublime_plugin_lib.panels import OutputPanel 18 | 19 | 20 | _logger = logging.getLogger(__name__) 21 | 22 | 23 | ON_COMPILER_PATH_AVAILABLE = 'OnCompilerPathAvailableEvent' 24 | ON_COMPLETIONS_REQUESTED = 'OnCompletionsRequestedEvent' 25 | 26 | _events = { 27 | ON_COMPILER_PATH_AVAILABLE: [], 28 | ON_COMPLETIONS_REQUESTED: [], 29 | } 30 | 31 | 32 | def add_listener(event_name, f): 33 | '''Registers a listener for the @event_name event. 34 | ''' 35 | assert event_name, 'must provide "event_name" (actual: %s)' % event_name 36 | assert event_name in _events, 'unknown event name: %s' % event_name 37 | if f not in _events: 38 | _events[event_name].append(f) 39 | 40 | 41 | def raise_event(event_name=None, data={}): 42 | '''Raises an event. 43 | ''' 44 | assert event_name, 'must provide "event_name" (actual: %s)' % event_name 45 | assert event_name in _events, 'unknown event name: %s' % event_name 46 | assert isinstance(data, dict), '`data` must be a dict' 47 | for f in _events[event_name]: 48 | f(data) 49 | 50 | 51 | def process_resp(data): 52 | _logger.debug ('processing response data: %s', data) 53 | if data ['Kind'] == 'compilerlocation': 54 | r = CompilerLocationResponse (data) 55 | raise_event(ON_COMPILER_PATH_AVAILABLE, {'response': r}) 56 | return 57 | 58 | if data['Kind'] == 'project': 59 | r = ProjectResponse(data) 60 | _logger.debug('\n'.join(r.files)) 61 | return 62 | 63 | if data['Kind'] == 'errors': 64 | # todo: enable error navigation via standard keys 65 | v = sublime.active_window().active_view() 66 | v.erase_regions ('fs.errs') 67 | if not data['Data']: 68 | return 69 | v.add_regions('fs.errs', 70 | [ErrorInfo(e).to_region(v) for e in data['Data']], 71 | 'invalid.illegal', 72 | 'dot', 73 | sublime.DRAW_SQUIGGLY_UNDERLINE | 74 | sublime.DRAW_NO_FILL | 75 | sublime.DRAW_NO_OUTLINE 76 | ) 77 | return 78 | 79 | if data['Kind'] == 'ERROR': 80 | _logger.error(str(data)) 81 | return 82 | 83 | if data['Kind'] == 'tooltip' and data['Data']: 84 | v = sublime.active_window().active_view() 85 | word = v.substr(v.word(v.sel()[0].b)) 86 | panel = OutputPanel('fs.out') 87 | panel.write(data['Data']) 88 | panel.show() 89 | return 90 | 91 | if data['Kind'] == 'INFO' and data['Data']: 92 | _logger.info(str(data)) 93 | print("FSharp:", data['Data']) 94 | return 95 | 96 | if data['Kind'] == 'finddecl' and data['Data']: 97 | fname = data['Data']['File'] 98 | row = data['Data']['Line'] 99 | col = data['Data']['Column'] + 1 100 | w = sublime.active_window() 101 | # todo: don't open file if we are looking at the requested file 102 | target = '{0}:{1}:{2}'.format(fname, row, col) 103 | w.open_file(target, sublime.ENCODED_POSITION) 104 | return 105 | 106 | if data['Kind'] == 'declarations' and data['Data']: 107 | decls = DeclarationsResponse(data) 108 | its = [decl.to_menu_data() for decl in decls.declarations] 109 | w = sublime.active_window() 110 | w.run_command ('fs_show_menu', {'items': its}) 111 | return 112 | 113 | if data['Kind'] == 'completion' and data['Data']: 114 | _logger.error('unexpected "completion" results - should be handled elsewhere') 115 | return 116 | -------------------------------------------------------------------------------- /FSharp.CompilerBinding/FSharp.CompilerBinding.fsproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {88F6940F-D300-474C-B2A7-E2ECD5B04B57} 9 | Library 10 | FSharp.CompilerBinding 11 | False 12 | FSharp.CompilerBinding 13 | v4.5 14 | ..\FSharp.AutoComplete\ 15 | true 16 | 4.3.0.0 17 | 11 18 | 19 | 20 | 21 | True 22 | full 23 | False 24 | bin\Debug 25 | DEBUG 26 | prompt 27 | False 28 | False 29 | --warnon:1182 30 | 31 | 32 | True 33 | pdbonly 34 | True 35 | bin\Release 36 | TRACE 37 | prompt 38 | True 39 | False 40 | 41 | 42 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets 43 | 44 | 45 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets 46 | 47 | 48 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | True 67 | 68 | 69 | 70 | 71 | 72 | ..\lib\mono.cecil\Mono.Cecil.dll 73 | 74 | 75 | $(SolutionDir)\packages\FSharp.Compiler.Service.0.0.85\lib\net45\FSharp.Compiler.Service.dll 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /emacs/test/fsharp-mode-tests.el: -------------------------------------------------------------------------------- 1 | ;;; Test registration of auto modes. 2 | 3 | (defmacro check-automode (extension) 4 | `(check ,(concat "uses fsharp-mode for " extension " files") 5 | (using-temp-file ,extension 6 | (should (eq major-mode 'fsharp-mode))))) 7 | 8 | (check-automode ".fs") 9 | (check-automode ".fsx") 10 | (check-automode ".fsi") 11 | (check-automode ".fsl") 12 | 13 | ;;; Test our ability to find SLN files and projects. 14 | ;;; This is tricky to test comprehensively because there is a sln at the 15 | ;;; root of this repo. 16 | 17 | (check "should not find fsharp project if none present" 18 | (should-not (fsharp-mode/find-sln-or-fsproj "/bin/"))) 19 | 20 | (check "should find fsproj in test project directory" 21 | (should-match "Test1.fsproj" 22 | (fsharp-mode/find-sln-or-fsproj fs-file-dir))) 23 | 24 | (check "should prefer sln to fsproj" 25 | (should-match "bar.sln" 26 | (fsharp-mode/find-sln-or-fsproj (concat test-dir 27 | "FindSlnData/")))) 28 | 29 | (check "should find closest sln" 30 | (should-match "foo.sln" 31 | (fsharp-mode/find-sln-or-fsproj (concat test-dir 32 | "FindSlnData/" 33 | "sln/")))) 34 | 35 | (check "should find sln in parent dir" 36 | (should-match "bar.sln" 37 | (fsharp-mode/find-sln-or-fsproj (concat test-dir 38 | "FindSlnData/" 39 | "noproj/" 40 | "test.fs")))) 41 | 42 | ;;; Test correct construction of compile commands 43 | 44 | (check "Should use make if Makefile present" 45 | (should-match "make -k" 46 | (fsharp-mode-choose-compile-command (concat test-dir 47 | "CompileCommandData/" 48 | "proj/" 49 | "test.fs")))) 50 | 51 | (check "Should use xbuild if fsproj present" 52 | (should-match "\\(x\\|ms\\)build.* /nologo .*Test1.fsproj" 53 | (fsharp-mode-choose-compile-command (concat test-dir 54 | "Test1/" 55 | "Program.fs")))) 56 | 57 | (check "Should use fsc if no fsproj present" 58 | (should-match "fs\\(harp\\)?c.* --nologo .*test.fs" 59 | (fsharp-mode-choose-compile-command (concat test-dir 60 | "CompileCommandData/" 61 | "noproj/" 62 | "test.fs")))) 63 | 64 | (check "Should quote filenames in xbuild mode" 65 | (should-match "\\(x\\|ms\\)build.* /nologo .*\".*Directory With Spaces/proj/test.fsproj\"" 66 | (fsharp-mode-choose-compile-command (concat test-dir 67 | "CompileCommandData/" 68 | "Directory With Spaces/" 69 | "proj/" 70 | "empty.fs")))) 71 | 72 | (check "Should quote filenames in fsc mode" 73 | (should-match "fs\\(harp\\)?c.* --nologo .*\".*Directory With Spaces/noproj/test.fs\"" 74 | (fsharp-mode-choose-compile-command (concat test-dir 75 | "CompileCommandData/" 76 | "Directory With Spaces/" 77 | "noproj/" 78 | "test.fs")))) 79 | (check "Should quote builder in xbuild mode" 80 | (let ((fsharp-build-command "/path with spaces/xbuild")) 81 | (should-match "\"/path with spaces/xbuild\"" 82 | (fsharp-mode-choose-compile-command (concat test-dir 83 | "CompileCommandData/" 84 | "Directory With Spaces/" 85 | "proj/" 86 | "test.fs"))))) 87 | -------------------------------------------------------------------------------- /sublimetext/FSharp/sublime_plugin_lib/fs_completion.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014, Guillermo López-Anglada. Please see the AUTHORS file for details. 2 | # All rights reserved. Use of this source code is governed by a BSD-style 3 | # license that can be found in the LICENSE file.) 4 | 5 | 6 | # TODO(guillermooo): get fsystem items async 7 | # TODO(guillermooo): set limits to the no. of returned items 8 | # TODO(guillermooo): handle OS errors like permissions, etc. 9 | # TODO(guillermooo): performance: maybe store items in a tree, 10 | # skip list or some sort of indexed structure that improves recall time, 11 | # like indexing by prefix: 12 | # a, b, c, d, e, f, g ... ah, bh, ch, dh 13 | 14 | 15 | from collections import Counter 16 | import os 17 | import glob 18 | 19 | 20 | class CompletionsList(object): 21 | def __init__(self, items): 22 | self.items = items 23 | 24 | def __iter__(self): 25 | yield from self.items 26 | 27 | # TODO(guillermooo): move casesensitive to __init__ 28 | def iter_prefixed(self, prefix, casesensitive=False): 29 | if casesensitive: 30 | yield from (item for item in self 31 | if item.startswith(prefix)) 32 | else: 33 | yield from (item for item in self 34 | if item.lower().startswith(prefix.lower())) 35 | 36 | 37 | class FileSystemCompletion(object): 38 | def __init__(self, casesensitive=False): 39 | self.cached_items = None 40 | # path as provided by user 41 | self.user_path = None 42 | # TODO(guillermooo): set automatically based on OS 43 | self._casesensitive = casesensitive 44 | 45 | def do_refresh(self, new_path, force_refresh): 46 | seps_new = Counter(new_path)["/"] 47 | seps_old = Counter(self.user_path)["/"] 48 | 49 | # we've never tried to get completions yet, so try now 50 | if self.cached_items is None: 51 | self.user_path = os.path.abspath('.') 52 | return True 53 | 54 | # if we have 2 or more additional slashes, we can be sure the user 55 | # wants to drill down to a different directory. 56 | # if we had only 1 additional slash, it may indicate a directory, but 57 | # not necessarily any user-driven intention of drilling down in the 58 | # dir hierarchy. This is because we return items with slashes to 59 | # indicate directories. 60 | # 61 | # If we have fewer slashes in the new path, the user has modified it. 62 | if 0 > (seps_new - seps_old) > 1 or (seps_new - seps_old) < 0: 63 | return True 64 | 65 | return force_refresh 66 | 67 | def get_completions(self, path, force_refresh=False): 68 | # we are cycling through items in the same directory as last time, 69 | # so reuse the cached items 70 | if not self.do_refresh(path, force_refresh): 71 | cl = CompletionsList(self.cached_items) 72 | leaf = os.path.split(path)[1] 73 | return list(cl.iter_prefixed( 74 | leaf, 75 | casesensitive=self._casesensitive) 76 | ) 77 | 78 | # we need to refresh the cache, as we are in a different directory 79 | # now or we've been asked to nevertheless. 80 | self.user_path = self.unescape(path) 81 | abs_path = os.path.abspath(os.path.dirname(self.user_path)) 82 | leaf = os.path.split(self.user_path)[1] 83 | 84 | fs_items = glob.glob(self.user_path + '*') 85 | fs_items = self.process_items(fs_items) 86 | 87 | cl = CompletionsList(fs_items) 88 | self.cached_items = list(cl) 89 | 90 | return list(cl.iter_prefixed(leaf, 91 | casesensitive=self._casesensitive) 92 | ) 93 | 94 | def process_items(self, items): 95 | processed = [] 96 | for it in items: 97 | if not os.path.isdir(it): 98 | continue 99 | leaf = os.path.split(it)[1] 100 | leaf += '/' 101 | processed.append(self.escape(leaf)) 102 | return processed 103 | 104 | @classmethod 105 | def escape(cls, name): 106 | return name.replace(' ', '\\ ') 107 | 108 | @classmethod 109 | def unescape(cls, name): 110 | return name.replace('\\ ', ' ') 111 | -------------------------------------------------------------------------------- /sublimetext/FSharp/tests/lib/test_project.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | import glob 3 | import os 4 | import tempfile 5 | import time 6 | import unittest 7 | 8 | import sublime 9 | 10 | from FSharp.lib.project import find_fsproject 11 | from FSharp.lib.project import FSharpFile 12 | from FSharp.lib.project import FSharpProjectFile 13 | from FSharp.sublime_plugin_lib.io import touch 14 | 15 | 16 | @contextlib.contextmanager 17 | def make_directories(dirs): 18 | tmp_dir = tempfile.TemporaryDirectory() 19 | current = tmp_dir.name 20 | for dd in dirs: 21 | for d in dd: 22 | current = os.path.join(current, d) 23 | os.mkdir(current) 24 | current = tmp_dir.name 25 | yield tmp_dir.name 26 | tmp_dir.cleanup() 27 | 28 | 29 | class Test_find_fsproject(unittest.TestCase): 30 | def testCanFind(self): 31 | with make_directories([["foo", "bar", "baz"]]) as tmp_root: 32 | fs_proj_file = os.path.join(tmp_root, 'hey.fsproj') 33 | touch(fs_proj_file) 34 | found = find_fsproject (os.path.join (tmp_root, 'foo/bar/baz')) 35 | self.assertEquals(found, fs_proj_file) 36 | 37 | 38 | class Test_FSharpProjectFile (unittest.TestCase): 39 | def testCanCreateFromPath(self): 40 | with tempfile.TemporaryDirectory () as tmp: 41 | f = os.path.join (tmp, 'foo.fsproj') 42 | touch (f) 43 | fs_project = FSharpProjectFile.from_path(f) 44 | self.assertEquals(fs_project.path, f) 45 | 46 | def testCanReturnParent(self): 47 | with tempfile.TemporaryDirectory () as tmp: 48 | f = os.path.join (tmp, 'foo.fsproj') 49 | touch (f) 50 | fs_project = FSharpProjectFile.from_path(f) 51 | self.assertEquals(fs_project.parent, tmp) 52 | 53 | def testCanBeCompared(self): 54 | with tempfile.TemporaryDirectory () as tmp: 55 | f = os.path.join (tmp, 'foo.fsproj') 56 | touch (f) 57 | fs_project_1 = FSharpProjectFile.from_path(f) 58 | fs_project_2 = FSharpProjectFile.from_path(f) 59 | self.assertEquals(fs_project_1, fs_project_2) 60 | 61 | def test_governs_SameLevel(self): 62 | with tempfile.TemporaryDirectory () as tmp: 63 | f = os.path.join (tmp, 'foo.fsproj') 64 | f2 = os.path.join (tmp, 'foo.fs') 65 | touch (f) 66 | touch (f2) 67 | fs_proj = FSharpProjectFile.from_path(f) 68 | self.assertTrue(fs_proj.governs (f2)) 69 | 70 | 71 | class Test_FSharpFile (unittest.TestCase): 72 | def setUp(self): 73 | self.win = sublime.active_window() 74 | 75 | def tearDown(self): 76 | self.win.run_command ('close') 77 | 78 | def testCanDetectCodeFile(self): 79 | with tempfile.TemporaryDirectory () as tmp: 80 | f = os.path.join (tmp, 'foo.fs') 81 | touch (f) 82 | v = self.win.open_file(f) 83 | time.sleep(0.01) 84 | fs_file = FSharpFile (v) 85 | self.assertTrue (fs_file.is_code_file) 86 | 87 | def testCanDetectScriptFile(self): 88 | with tempfile.TemporaryDirectory () as tmp: 89 | f = os.path.join (tmp, 'foo.fsx') 90 | touch (f) 91 | v = self.win.open_file(f) 92 | time.sleep(0.01) 93 | fs_file = FSharpFile (v) 94 | self.assertTrue (fs_file.is_script_file) 95 | 96 | def testCanDetectCodeForCodeFile(self): 97 | with tempfile.TemporaryDirectory () as tmp: 98 | f = os.path.join (tmp, 'foo.fs') 99 | touch (f) 100 | v = self.win.open_file(f) 101 | time.sleep(0.01) 102 | fs_file = FSharpFile (v) 103 | self.assertTrue (fs_file.is_code) 104 | 105 | def testCanDetectCodeForScriptFile(self): 106 | with tempfile.TemporaryDirectory () as tmp: 107 | f = os.path.join (tmp, 'foo.fsx') 108 | touch (f) 109 | v = self.win.open_file(f) 110 | time.sleep(0.01) 111 | fs_file = FSharpFile (v) 112 | self.assertTrue (fs_file.is_code) 113 | 114 | def testCanDetectProjectFile(self): 115 | with tempfile.TemporaryDirectory () as tmp: 116 | f = os.path.join (tmp, 'foo.fsproj') 117 | touch (f) 118 | v = self.win.open_file(f) 119 | time.sleep(0.01) 120 | fs_file = FSharpFile (v) 121 | self.assertTrue (fs_file.is_project_file) 122 | -------------------------------------------------------------------------------- /emacs/fsharp-doc.el: -------------------------------------------------------------------------------- 1 | ;;; fsharp-doc.el -- show information for F# symbol at point. 2 | ;; 3 | ;; Filename: fsharp-doc.el 4 | ;; Author: Chris Barrett 5 | ;; Maintainer: Chris Barrett 6 | ;; Keywords: fsharp, languages 7 | ;; 8 | ;; This file is not part of GNU Emacs. 9 | ;; 10 | ;; This program is free software; you can redistribute it and/or 11 | ;; modify it under the terms of the GNU General Public License as 12 | ;; published by the Free Software Foundation; either version 3, or 13 | ;; (at your option) any later version. 14 | ;; 15 | ;; This program is distributed in the hope that it will be useful, 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 | ;; General Public License for more details. 19 | ;; 20 | ;; You should have received a copy of the GNU General Public License 21 | ;; along with this program; see the file COPYING. If not, write to 22 | ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth 23 | ;; Floor, Boston, MA 02110-1301, USA. 24 | ;; 25 | ;;; Commentary: 26 | ;; 27 | ;; This is part of fsharp-mode for Emacs. It communicates with the F# 28 | ;; completion process to provide information for the symbol at point. 29 | ;; 30 | ;; This should be loaded automatically by fsharp-mode. Otherwise, add 31 | ;; this file to your load path, then call 32 | ;; 33 | ;; (autoload 'turn-on-fsharp-doc-mode "fsharp-doc.el") 34 | ;; (add-hook 'fsharp-mode-hook 'turn-on-fsharp-doc-mode) 35 | ;; 36 | ;;; Code: 37 | 38 | (with-no-warnings (require 'cl)) 39 | (require 'fsharp-mode-completion) 40 | 41 | (defvar fsharp-doc-idle-delay 0.5 42 | "The number of seconds to wait for input idle before showing a tooltip.") 43 | 44 | (define-minor-mode fsharp-doc-mode 45 | "Display F# documentation in the minibuffer." 46 | nil 47 | "" 48 | nil 49 | ;; Body 50 | (fsharp-doc-reset-timer) 51 | (when fsharp-doc-mode 52 | (fsharp-doc-start-timer) 53 | (run-hooks 'fsharp-doc-mode-hook)) 54 | fsharp-doc-mode) 55 | 56 | (defun turn-on-fsharp-doc-mode () 57 | (fsharp-doc-mode t)) 58 | 59 | (defun turn-off-fsharp-doc-mode () 60 | (fsharp-doc-mode nil)) 61 | 62 | ;;; ----------------------------------------------------------------------------- 63 | 64 | (defvar fsharp-doc-timer nil) 65 | 66 | (defun fsharp-doc-start-timer () 67 | (unless fsharp-doc-timer 68 | (setq fsharp-doc-timer 69 | (run-with-idle-timer fsharp-doc-idle-delay t 70 | 'fsharp-doc-show-tooltip)))) 71 | 72 | (defun fsharp-doc-reset-timer () 73 | (when fsharp-doc-timer 74 | (cancel-timer fsharp-doc-timer) 75 | (setq fsharp-doc-timer nil))) 76 | 77 | ;;; ---------------------------------------------------------------------------- 78 | 79 | (defun fsharp-doc/format-for-minibuffer (str) 80 | "Parse the result from the F# process." 81 | (destructuring-bind (x &rest xs) (split-string str "[\r\n]") 82 | (let ((line (if (string-match-p "^Multiple" x) (car-safe xs) x)) 83 | (name (fsharp-doc-extract-full-name str))) 84 | (fsharp-doc-tidy-result 85 | (cond 86 | ;; Don't fully-qualify let-bindings. 87 | ((string-match-p "^val" line) 88 | line) 89 | 90 | ;; Extract type identifier. 91 | (name 92 | (fsharp-doc-replace-identifier line name)) 93 | 94 | (t 95 | line)))))) 96 | 97 | (defun fsharp-doc-extract-full-name (str) 98 | (when (string-match "Full name: \\(.*\\)$" str) 99 | (match-string 1 str))) 100 | 101 | (defun fsharp-doc-replace-identifier (str fullname) 102 | (replace-regexp-in-string 103 | "^\\w+ \\(public \\|private \\|internal \\)?\\(.*?\\) " 104 | fullname str 'fixcase "\2" 2)) 105 | 106 | (defun fsharp-doc-tidy-result (str) 107 | (replace-regexp-in-string "[ ]*=[ ]*" "" str)) 108 | 109 | ;;; ---------------------------------------------------------------------------- 110 | 111 | (defvar fsharp-doc-prevpoint nil) 112 | 113 | (defun fsharp-doc-show-tooltip () 114 | "Show tooltip info in the minibuffer. 115 | If there is an error or warning at point, show the error text. 116 | Otherwise, request a tooltip from the completion process." 117 | (interactive) 118 | (when (and fsharp-doc-mode (thing-at-point 'symbol)) 119 | (unless (or (equal (point) fsharp-doc-prevpoint) 120 | (not (eq fsharp-ac-status 'idle)) 121 | executing-kbd-macro 122 | (fsharp-ac/overlay-at (point)) 123 | (active-minibuffer-window) 124 | cursor-in-echo-area) 125 | (setq fsharp-doc-prevpoint (point)) 126 | (fsharp-ac/show-typesig-at-point t)))) 127 | 128 | (provide 'fsharp-doc) 129 | 130 | ;;; fsharp-doc.el ends here 131 | -------------------------------------------------------------------------------- /vim/ftplugin/fsharp.vim: -------------------------------------------------------------------------------- 1 | " Vim filetype plugin 2 | " Language: F# 3 | " Last Change: Thu 23 Oct 2014 08:39:53 PM CEST 4 | " Maintainer: Gregor Uhlenheuer 5 | 6 | if exists('b:did_ftplugin') 7 | finish 8 | endif 9 | let b:did_ftplugin = 1 10 | 11 | let s:cpo_save = &cpo 12 | set cpo&vim 13 | 14 | let s:candidates = [ 'fsi', 15 | \ 'fsi.exe', 16 | \ 'fsharpi', 17 | \ 'fsharpi.exe' ] 18 | 19 | let g:fsharp_onfly_error_check = 1 20 | 21 | if !exists('g:fsharp_interactive_bin') 22 | let g:fsharp_interactive_bin = '' 23 | for c in s:candidates 24 | if executable(c) 25 | let g:fsharp_interactive_bin = c 26 | endif 27 | endfor 28 | endif 29 | 30 | " check for python support 31 | if has('python') 32 | python <:p:h')") 36 | file_dir = vim.eval("expand('%:p:h')") 37 | sys.path.append(fsharp_dir) 38 | 39 | from fsharpvim import FSAutoComplete,Statics 40 | from fsi import FSharpInteractive 41 | import pyvim 42 | 43 | if Statics.fsac == None: 44 | debug = vim.eval("get(g:, 'fsharpbinding_debug', 0)") != '0' 45 | Statics.fsac = FSAutoComplete(fsharp_dir, debug) 46 | if Statics.fsi == None: 47 | debug = vim.eval("get(g:, 'fsharpbinding_debug', 0)") != '0' 48 | Statics.fsi = FSharpInteractive(vim.eval('g:fsharp_interactive_bin'), debug) 49 | fsautocomplete = Statics.fsac 50 | fsi = Statics.fsi 51 | 52 | #find project file if any - assumes fsproj file will be in the same directory as the fs or fsi file 53 | b = vim.current.buffer 54 | x,ext = os.path.splitext(b.name) 55 | if '.fs' == ext or '.fsi' == ext: 56 | dir = os.path.dirname(os.path.realpath(b.name)) 57 | projs = filter(lambda f: '.fsproj' == os.path.splitext(f)[1], os.listdir(dir)) 58 | if len(projs): 59 | proj_file = os.path.join(dir, projs[0]) 60 | vim.command("let b:proj_file = '%s'" % proj_file) 61 | fsautocomplete.project(proj_file) 62 | fsautocomplete.parse(b.name, True, b) 63 | EOF 64 | 65 | nnoremap t :call fsharpbinding#python#TypeCheck() 66 | nnoremap d :call fsharpbinding#python#GotoDecl() 67 | nnoremap s :call fsharpbinding#python#GoBackFromDecl() 68 | 69 | com! -buffer LogFile call fsharpbinding#python#LoadLogFile() 70 | com! -buffer -nargs=* -complete=file ParseProject call fsharpbinding#python#ParseProject() 71 | com! -buffer -nargs=* -complete=file BuildProject call fsharpbinding#python#BuildProject() 72 | com! -buffer -nargs=* -complete=file RunTests call fsharpbinding#python#RunTests() 73 | com! -buffer -nargs=* -complete=file RunProject call fsharpbinding#python#RunProject() 74 | 75 | "fsi 76 | com! -buffer FsiShow call fsharpbinding#python#FsiShow() 77 | com! -buffer FsiRead call fsharpbinding#python#FsiRead(0.5) "short timeout as there may not be anything to read 78 | com! -buffer FsiReset call fsharpbinding#python#FsiReset(g:fsharp_interactive_bin) 79 | com! -buffer -nargs=1 FsiEval call fsharpbinding#python#FsiEval() 80 | com! -buffer FsiEvalBuffer call fsharpbinding#python#FsiSendAll() 81 | 82 | nnoremap  :call fsharpbinding#python#FsiSendLine() 83 | vnoremap  :call fsharpbinding#python#FsiSendSel() 84 | nnoremap i :call fsharpbinding#python#FsiSendLine() 85 | vnoremap i :call fsharpbinding#python#FsiSendSel() 86 | 87 | augroup fsharpbindings_au 88 | au! 89 | " closing the scratch window after leaving insert mode 90 | " is common practice 91 | au BufWritePre *.fs,*.fsi,*fsx call fsharpbinding#python#OnBufWritePre() 92 | if version > 703 93 | " these events new in Vim 7.4 94 | au TextChanged *.fs,*.fsi,*fsx call fsharpbinding#python#OnTextChanged() 95 | au TextChangedI *.fs,*.fsi,*fsx call fsharpbinding#python#OnTextChangedI() 96 | au CursorHold *.fs,*.fsi,*fsx call fsharpbinding#python#OnCursorHold() 97 | au InsertLeave *.fs,*.fsi,*fsx call fsharpbinding#python#OnInsertLeave() 98 | endif 99 | au BufEnter *.fs,*.fsi,*fsx call fsharpbinding#python#OnBufEnter() 100 | au InsertLeave *.fs,*.fsi,*fsx if pumvisible() == 0|silent! pclose|endif 101 | augroup END 102 | 103 | " omnicomplete 104 | setlocal omnifunc=fsharpbinding#python#Complete 105 | endif 106 | 107 | " enable syntax based folding 108 | setl fdm=syntax 109 | 110 | " comment settings 111 | setl formatoptions=croql 112 | setl commentstring=(*%s*) 113 | setl comments=s0:*\ -,m0:*\ \ ,ex0:*),s1:(*,mb:*,ex:*),:\/\/\/,:\/\/ 114 | 115 | " make ftplugin undo-able 116 | let b:undo_ftplugin = 'setl fo< cms< com< fdm<' 117 | 118 | let &cpo = s:cpo_save 119 | 120 | " vim: sw=4 et sts=4 121 | -------------------------------------------------------------------------------- /FSharp.AutoComplete/README.md: -------------------------------------------------------------------------------- 1 | # FSharp.AutoComplete 2 | 3 | This project provides a command-line interface to the [FSharp.Compiler.Service](https://github.com/fsharp/FSharp.Compiler.Service/) project. It is intended to be used as a backend service for rich editing or 'intellisense' features for editors. Currently it is used by the [emacs](../emacs) support. 4 | 5 | This README is targeted at developers. 6 | 7 | ## Building and testing 8 | 9 | There is a [FAKE script](build.fsx) with chain-loaders for [*nix](fake) and [Windows](fake.cmd). This can be used for both building and running the unit and integration tests. It is also the core of the CI builds running on [Travis](../.travis.yml) and [AppVeyor](../appveyor.yml), and so also has the ability to run the Emacs unit and integration tests. 10 | 11 | On Linux and OSX, there is a legacy [Makefile](Makefile), which is a bit quicker to run (the overhead of running launching FSI for Fake is a few seconds). For the moment this supports all the same functionality that the FAKE script does, but this will not likely continue to be the case. 12 | 13 | The [integration tests](integration) use a simple strategy of running a scripted session with `fsautocomplete.exe` and then comparing the output with that saved in the repository. This requires careful checking when the test is first constructed. On later runs, absolute paths are removed using regular expressions to ensure that the tests are machine-independent. 14 | 15 | There are not currently any unit tests, the previously tested functionality of project parsing has been moved upstream to [FSharp.Compiler.Service](https://github.com/fsharp/FSharp.Compiler.Service). The tests were simply constructed using NUnit and FSUnit. If a new test is required, you can look back through the history for the `unit` directory and use that structure. 16 | 17 | ## Communication protocol 18 | 19 | It is expected that the editor will launch this program in the background and communicate over a pipe. It is possible to use interactively, although due to the lack of any readline support it isn't pleasant, and text pasted into the buffer may not be echoed. As a result, use this only for very simple debugging. For more complex scenarios it is better to write another integration test by copying an [existing one](test/integration/Test1). 20 | 21 | The available commands can be listed by running `fsautocomplete.exe` and entering `help`. Commands are all on a single line, with the exception of the `parse` command, which should be followed by the current text of the file to parse (which may differ from the contents on disk), and terminated with a line containing only `<>`. 22 | 23 | There are two formats for data to be returned in: text and JSON. The text support is the default, and provided for backwards compatibility and testing. An example of a session in 'text' mode is: 24 | 25 | project "Test1.fsproj" 26 | /Program.fs 27 | <> 28 | parse "Program.fs" 29 | module X = 30 | let func x = x + 1 31 | 32 | let val2 = X.func 2 33 | <> 34 | INFO: Background parsing started 35 | completion "Program.fs" 4 13 36 | DATA: completion 37 | func 38 | <> 39 | 40 | Notice that the program locations are 1-indexed for both lines and columns (here 4 and 13 to select the point just after `X.`). In this text mode, multiline responses are terminated with `<>`. This clumsiness was the reason for moving to JSON. 41 | 42 | Editors will want to use the JSON mode for preference, selected by sending the command `outputmode json`. The same simple session using JSON would look like: 43 | 44 | outputmode json 45 | project "Test1.fsproj" 46 | {"Kind":"project","Data":{"Files":["/Program.fs"],"Output":"/bin/Debug/Test1.exe"}} 47 | parse "Program.fs" 48 | module X = 49 | let func x = x + 1 50 | 51 | let val2 = X.func 2 52 | <> 53 | {"Kind":"INFO","Data":"Background parsing started"} 54 | completion "Program.fs" 4 13 55 | {"Kind":"completion","Data":["func"]} 56 | 57 | The structured data returned is able to be richer. Note for example that the output of the project is also returned. Parsing is also simplified (given a JSON parser!) because each response is exactly one line. However, it is less human-readable, which is why it is not currently used for most of the integration tests. 58 | 59 | For further insight into the communication protocol, have a look over the integration tests, which have examples of all the features. Each folder contains one or more `*Runner.fsx` files which specify a sequence of commands to send, and `*.txt` or `*.json` files, which contain the output. 60 | 61 | ### Scripts and projects 62 | 63 | Currently, intellisense can be offered for any number of scripts and one project at any one time. Intellisense requests are honoured for any script (`.fsx`) file and any `.fs` file for which a project containing it has most recently been loaded using the `project` command. It is an aim to lift this limitation. 64 | 65 | --------------------------------------------------------------------------------