tfausak / purple-yolk

:hatching_chick: A Haskell IDE for Visual Studio Code.
https://marketplace.visualstudio.com/items?itemName=taylorfausak.purple-yolk
MIT License
26 stars 2 forks source link

Make extension work for a single Haskell file without workspace #79

Closed EduardSergeev closed 1 month ago

EduardSergeev commented 1 month ago

Even though the current documentation says:

Although Purple Yolk can work with a single Haskell file, its utility is somewhat limited.

when I attempt to open a single Haskell file without workspace, e.g. via:

code tmp.hs

no diagnostics is emitted while Purple Yolk log contains the following:

2024-05-09T21:54:55.003Z [6f02] Activating purple-yolk version 1.0.5 ...
2024-05-09T21:54:55.004Z [ed8f] Getting Haskell interpreter ...
2024-05-09T21:54:55.004Z [ed8f] Requested Haskell interpreter mode is discover
2024-05-09T21:54:55.004Z [ed8f] Actual Haskell interpreter mode is custom
2024-05-09T21:54:55.004Z [4c21] Getting Haskell formatter ...
2024-05-09T21:54:55.004Z [4c21] Requested Haskell formatter mode is discover
2024-05-09T21:54:55.004Z [27ea] Getting Haskell linter ...
2024-05-09T21:54:55.004Z [27ea] Requested Haskell linter mode is discover
2024-05-09T21:54:55.004Z [509e] Getting Cabal formatter ...
2024-05-09T21:54:55.004Z [509e] Requested Cabal formatter mode is discover
2024-05-09T21:54:55.012Z [4c21] Actual Haskell formatter mode is discover
2024-05-09T21:54:55.012Z [509e] Actual Cabal formatter mode is discover
2024-05-09T21:54:55.012Z [27ea] Actual Haskell linter mode is discover
2024-05-09T21:54:55.012Z [028b] Starting interpreter ...
2024-05-09T21:54:55.012Z [028b] Error: Missing workspace folder!
2024-05-09T21:54:55.012Z [6f02] Successfully activated in 0.009 seconds.

When the same file is opened in a workspace (in a separate folder but without Cabal or Stack setup) still no diagnostics is emitted while Purple Yolk log contains the following:

2024-05-09T21:59:48.343Z [d799] Activating purple-yolk version 1.0.5 ...
2024-05-09T21:59:48.343Z [d357] Getting Haskell interpreter ...
2024-05-09T21:59:48.343Z [d357] Requested Haskell interpreter mode is discover
2024-05-09T21:59:48.343Z [d357] Actual Haskell interpreter mode is custom
2024-05-09T21:59:48.343Z [264e] Getting Haskell formatter ...
2024-05-09T21:59:48.343Z [264e] Requested Haskell formatter mode is discover
2024-05-09T21:59:48.344Z [b1c4] Getting Haskell linter ...
2024-05-09T21:59:48.344Z [b1c4] Requested Haskell linter mode is discover
2024-05-09T21:59:48.344Z [1dcb] Getting Cabal formatter ...
2024-05-09T21:59:48.344Z [1dcb] Requested Cabal formatter mode is discover
2024-05-09T21:59:48.362Z [b1c4] Actual Haskell linter mode is discover
2024-05-09T21:59:48.362Z [1dcb] Actual Cabal formatter mode is discover
2024-05-09T21:59:48.366Z [264e] Actual Haskell formatter mode is discover
2024-05-09T21:59:48.366Z [3a95] Starting interpreter ...
2024-05-09T21:59:48.367Z [3a95] Running "stack ghci --ghci-options -ddump-json" in "/home/edka/work/Haskell/Test" ...
2024-05-09T21:59:48.370Z [3a95] [stdin] :set prompt "{- purple-yolk 1.0.5 3a95 -}\n"
2024-05-09T21:59:48.370Z [d799] Successfully activated in 0.028 seconds.
2024-05-09T21:59:48.653Z [3a95] [stderr] 
2024-05-09T21:59:48.653Z [3a95] [stderr] Note: No local targets specified, so a plain ghci will be started with no package hiding or package
2024-05-09T21:59:48.653Z [3a95] [stderr]       options.
2024-05-09T21:59:48.653Z [3a95] [stderr]       
2024-05-09T21:59:48.653Z [3a95] [stderr]       You are using snapshot: lts-21.19
2024-05-09T21:59:48.653Z [3a95] [stderr]       
2024-05-09T21:59:48.653Z [3a95] [stderr]       If you want to use package hiding and options, then you can try one of the following:
2024-05-09T21:59:48.653Z [3a95] [stderr]       
2024-05-09T21:59:48.653Z [3a95] [stderr]       * If you want to start a different project configuration
2024-05-09T21:59:48.653Z [3a95] [stderr]         than /home/edka/.stack/global-project/stack.yaml, then you can use stack init to create a
2024-05-09T21:59:48.653Z [3a95] [stderr]         new stack.yaml for the packages in the current directory. 
2024-05-09T21:59:48.653Z [3a95] [stderr]         
2024-05-09T21:59:48.653Z [3a95] [stderr]       * If you want to use the project configuration
2024-05-09T21:59:48.653Z [3a95] [stderr]         at /home/edka/.stack/global-project/stack.yaml, then you can add to its 'packages' field.
2024-05-09T21:59:48.653Z [3a95] [stderr]       
2024-05-09T21:59:48.743Z [3a95] [stderr] Configuring GHCi with the following packages:
2024-05-09T21:59:48.766Z [3a95] [stdout] GHCi, version 9.4.7: https://www.haskell.org/ghc/  :? for help
2024-05-09T21:59:48.796Z [3a95] [stdout] Loaded GHCi configuration from /home/edka/.cache/stack/ghci-script/2a3bbd58/ghci-script
2024-05-09T21:59:48.796Z [3a95] Successfully started in 0.430 seconds.
2024-05-09T22:00:07.040Z [23da] Reloading interpreter ...
2024-05-09T22:00:07.040Z [23da] [stdin] :reload
2024-05-09T22:00:07.042Z [23da] [stdout] Ok, no modules loaded.
2024-05-09T22:00:07.141Z [23da] Finished reloading in 0.101 seconds.
2024-05-09T22:00:17.037Z [5b13] Reloading interpreter ...
2024-05-09T22:00:17.037Z [5b13] [stdin] :reload
2024-05-09T22:00:17.039Z [5b13] [stdout] Ok, no modules loaded.
2024-05-09T22:00:17.138Z [5b13] Finished reloading in 0.102 seconds.

It would be useful to have Purple Yolk to work for bare Haskell files (i.e. single files without Cabal or Stack setup) preferably for both cases: opened with or without workspace.

tfausak commented 1 month ago

So there are two problems here:

EduardSergeev commented 1 month ago

Actually I only need the latter case (individual file without workspace). Simple GHC supports this mode (and I use it to run integration tests in Haskutil). I wanted to try using Purple Yolk for the same tests but I need single file mode for that.

I also think that this mode can be useful to others: sometimes you just want to test a simple Haskell expression or a small program so creating Cabal or Stack project for that is overkill.

EduardSergeev commented 1 month ago

Still does not work for a single file. No diagnostics is emitted. The output content is:

2024-05-10T03:29:00.793Z [0ca9] Activating purple-yolk version 1.0.6 ...
2024-05-10T03:29:00.793Z [0280] Getting Haskell interpreter ...
2024-05-10T03:29:00.793Z [0280] Requested Haskell interpreter mode is discover
2024-05-10T03:29:00.793Z [0280] Actual Haskell interpreter mode is custom
2024-05-10T03:29:00.793Z [d80a] Getting Haskell formatter ...
2024-05-10T03:29:00.793Z [d80a] Requested Haskell formatter mode is discover
2024-05-10T03:29:00.793Z [e139] Getting Haskell linter ...
2024-05-10T03:29:00.793Z [e139] Requested Haskell linter mode is discover
2024-05-10T03:29:00.794Z [a5f1] Getting Cabal formatter ...
2024-05-10T03:29:00.794Z [a5f1] Requested Cabal formatter mode is discover
2024-05-10T03:29:00.795Z [e139] Actual Haskell linter mode is discover
2024-05-10T03:29:00.795Z [a5f1] Actual Cabal formatter mode is discover
2024-05-10T03:29:00.799Z [d80a] Actual Haskell formatter mode is discover
2024-05-10T03:29:00.799Z [3d1d] Starting interpreter ...
2024-05-10T03:29:00.800Z [3d1d] Running "stack ghci --ghci-options -ddump-json" in "/home/edka/work/Haskell/Test" ...
2024-05-10T03:29:00.804Z [3d1d] [stdin] :set prompt "{- purple-yolk 1.0.6 3d1d -}\n"
2024-05-10T03:29:00.804Z [0ca9] Successfully activated in 0.012 seconds.
2024-05-10T03:29:01.124Z [3d1d] [stderr] 
2024-05-10T03:29:01.124Z [3d1d] [stderr] Note: No local targets specified, so a plain ghci will be started with no package hiding or package
2024-05-10T03:29:01.124Z [3d1d] [stderr]       options.
2024-05-10T03:29:01.124Z [3d1d] [stderr]       
2024-05-10T03:29:01.124Z [3d1d] [stderr]       You are using snapshot: lts-21.19
2024-05-10T03:29:01.124Z [3d1d] [stderr]       
2024-05-10T03:29:01.124Z [3d1d] [stderr]       If you want to use package hiding and options, then you can try one of the following:
2024-05-10T03:29:01.124Z [3d1d] [stderr]       
2024-05-10T03:29:01.124Z [3d1d] [stderr]       * If you want to start a different project configuration
2024-05-10T03:29:01.124Z [3d1d] [stderr]         than /home/edka/.stack/global-project/stack.yaml, then you can use stack init to create a
2024-05-10T03:29:01.124Z [3d1d] [stderr]         new stack.yaml for the packages in the current directory. 
2024-05-10T03:29:01.124Z [3d1d] [stderr]         
2024-05-10T03:29:01.124Z [3d1d] [stderr]       * If you want to use the project configuration
2024-05-10T03:29:01.124Z [3d1d] [stderr]         at /home/edka/.stack/global-project/stack.yaml, then you can add to its 'packages' field.
2024-05-10T03:29:01.124Z [3d1d] [stderr]       
2024-05-10T03:29:01.214Z [3d1d] [stderr] Configuring GHCi with the following packages:
2024-05-10T03:29:01.232Z [3d1d] [stdout] GHCi, version 9.4.7: https://www.haskell.org/ghc/  :? for help
2024-05-10T03:29:01.262Z [3d1d] [stdout] Loaded GHCi configuration from /home/edka/.cache/stack/ghci-script/2a3bbd58/ghci-script
2024-05-10T03:29:01.262Z [3d1d] Successfully started in 0.462 seconds.

For a single *.hs file (say, tmp.hs) instead of running stack ghci from the directory where tmp.hs file is located stack ghci tmp.hs must be execute. This will load the file and will emit all errors. To also get all possible warnings the file can be loaded via stack ghci tmp.hs --ghci-options -Wall command.

tfausak commented 1 month ago

That's happening because you have a custom interpreter set:

2024-05-10T03:29:00.793Z [0280] Getting Haskell interpreter ...
2024-05-10T03:29:00.793Z [0280] Requested Haskell interpreter mode is discover
2024-05-10T03:29:00.793Z [0280] Actual Haskell interpreter mode is custom

The discovery mechanism will always prefer the custom mode if it's set.

However even if you didn't have that, Purple Yolk would try to run ghci rather than stack ghci. In fact, PY will never try to run stack ghci for a single file — it only uses Stack for projects. In general I suspect it will be difficult to determine whether ghci ${file} or stack ghci ${file} should be used.

EduardSergeev commented 1 month ago

That's happening because you have a custom interpreter set

What do you mean by that? I have not changed any Purple Yolk settings, this is how it works (or rather doesn't) with a single file out of the box.

However even if you didn't have that, Purple Yolk would try to run ghci rather than stack ghci

This will not help either since I do not have GHC installed. But stack ghci tmp.hs should work.

Could you provide an example of Purple Yolk settings which would make it work for a single Haskell file (with only Stack installed)? Because the latest version with default settings still does not work. According to the logs it still tries to open the containing directory rather than the file:

My (default) settings:

image

Corresponding log:

2024-05-10T20:47:27.201Z [4cdc] Activating purple-yolk version 1.0.6 ...
2024-05-10T20:47:27.202Z [04df] Getting Haskell interpreter ...
2024-05-10T20:47:27.202Z [04df] Requested Haskell interpreter mode is discover
2024-05-10T20:47:27.202Z [e81d] Getting Haskell formatter ...
2024-05-10T20:47:27.202Z [e81d] Requested Haskell formatter mode is discover
2024-05-10T20:47:27.203Z [6014] Getting Haskell linter ...
2024-05-10T20:47:27.203Z [6014] Requested Haskell linter mode is discover
2024-05-10T20:47:27.203Z [8269] Getting Cabal formatter ...
2024-05-10T20:47:27.203Z [8269] Requested Cabal formatter mode is discover
2024-05-10T20:47:27.211Z [04df] Actual Haskell interpreter mode is stack
2024-05-10T20:47:27.211Z [6014] Actual Haskell linter mode is discover
2024-05-10T20:47:27.211Z [e81d] Actual Haskell formatter mode is discover
2024-05-10T20:47:27.211Z [8269] Actual Cabal formatter mode is discover
2024-05-10T20:47:27.211Z [5d86] Starting interpreter ...
2024-05-10T20:47:27.211Z [5d86] Running "stack ghci --ghci-options -ddump-json" in "/home/edka/work/Haskell/Test" ...
2024-05-10T20:47:27.215Z [5d86] [stdin] :set prompt "{- purple-yolk 1.0.6 5d86 -}\n"
2024-05-10T20:47:27.215Z [4cdc] Successfully activated in 0.014 seconds.
2024-05-10T20:47:27.516Z [5d86] [stderr] 
2024-05-10T20:47:27.516Z [5d86] [stderr] Note: No local targets specified, so a plain ghci will be started with no package hiding or package
2024-05-10T20:47:27.516Z [5d86] [stderr]       options.
2024-05-10T20:47:27.516Z [5d86] [stderr]       
2024-05-10T20:47:27.516Z [5d86] [stderr]       You are using snapshot: lts-21.19
2024-05-10T20:47:27.516Z [5d86] [stderr]       
2024-05-10T20:47:27.516Z [5d86] [stderr]       If you want to use package hiding and options, then you can try one of the following:
2024-05-10T20:47:27.516Z [5d86] [stderr]       
2024-05-10T20:47:27.516Z [5d86] [stderr]       * If you want to start a different project configuration
2024-05-10T20:47:27.516Z [5d86] [stderr]         than /home/edka/.stack/global-project/stack.yaml, then you can use stack init to create a
2024-05-10T20:47:27.516Z [5d86] [stderr]         new stack.yaml for the packages in the current directory. 
2024-05-10T20:47:27.516Z [5d86] [stderr]         
2024-05-10T20:47:27.516Z [5d86] [stderr]       * If you want to use the project configuration
2024-05-10T20:47:27.516Z [5d86] [stderr]         at /home/edka/.stack/global-project/stack.yaml, then you can add to its 'packages' field.
2024-05-10T20:47:27.516Z [5d86] [stderr]       
2024-05-10T20:47:27.602Z [5d86] [stderr] Configuring GHCi with the following packages:
2024-05-10T20:47:27.625Z [5d86] [stdout] GHCi, version 9.4.7: https://www.haskell.org/ghc/  :? for help
2024-05-10T20:47:27.653Z [5d86] [stdout] Loaded GHCi configuration from /home/edka/.cache/stack/ghci-script/2a3bbd58/ghci-script
2024-05-10T20:47:27.654Z [5d86] Successfully started in 0.443 seconds.

To reiterate for this scenario to work an individual *.hs file must be passed to stack ghci as a parameter, e.g.:

stack ghci tmp.hs --ghci-options -ddump-json --ghc-options -Wall

(note tmp.hs passed as a parameter)

EduardSergeev commented 1 month ago

Could you provide an example of Purple Yolk settings which would make it work for a single Haskell file (with only Stack installed)?

OK, I figured out it myself: just setting purple-yolk.haskell.interpreter.command to the below value makes this scenario work:

{
  "purple-yolk.haskell.interpreter.command": "stack ghci ${file} --ghci-options \"-ddump-json -Wall\""
}

image

Corresponding extension log:

2024-05-10T21:14:47.107Z [9a95] Getting Haskell interpreter ...
2024-05-10T21:14:47.107Z [9a95] Requested Haskell interpreter mode is discover
2024-05-10T21:14:47.107Z [9a95] Actual Haskell interpreter mode is custom
2024-05-10T21:14:47.107Z [d0a8] Getting Haskell formatter ...
2024-05-10T21:14:47.107Z [d0a8] Requested Haskell formatter mode is discover
2024-05-10T21:14:47.107Z [2aee] Getting Haskell linter ...
2024-05-10T21:14:47.107Z [2aee] Requested Haskell linter mode is discover
2024-05-10T21:14:47.107Z [ba66] Getting Cabal formatter ...
2024-05-10T21:14:47.107Z [ba66] Requested Cabal formatter mode is discover
2024-05-10T21:14:47.108Z [2aee] Actual Haskell linter mode is discover
2024-05-10T21:14:47.108Z [ba66] Actual Cabal formatter mode is discover
2024-05-10T21:14:47.133Z [d0a8] Actual Haskell formatter mode is discover
2024-05-10T21:14:47.133Z [a12a] Starting interpreter ...
2024-05-10T21:14:47.134Z [a12a] Running "stack ghci /home/edka/work/Haskell/Test/tmp.hs --ghci-options \"-ddump-json -Wall\"" in "/home/edka/work/Haskell/Test" ...
2024-05-10T21:14:47.137Z [a12a] [stdin] :set prompt "{- purple-yolk 1.0.6 a12a -}\n"
2024-05-10T21:14:47.137Z [09b7] Successfully activated in 0.031 seconds.
2024-05-10T21:14:47.314Z [a12a] [stderr] 
2024-05-10T21:14:47.314Z [a12a] [stderr] Warning: Couldn't find a component for file target /home/edka/work/Haskell/Test/tmp.hs. This means
2024-05-10T21:14:47.314Z [a12a] [stderr]          that the correct GHC options might not be used. Attempting to load the file anyway.
2024-05-10T21:14:47.489Z [a12a] [stderr] Configuring GHCi with the following packages:
2024-05-10T21:14:47.508Z [a12a] [stdout] GHCi, version 9.4.7: https://www.haskell.org/ghc/  :? for help
2024-05-10T21:14:47.539Z [a12a] [stdout] {"span":null,"doc":"[1 of 2] Compiling Main             ( /home/edka/work/Haskell/Test/tmp.hs, interpreted )","messageClass":"MCOutput"}
2024-05-10T21:14:47.551Z [a12a] [stdout] Ok, one module loaded.
2024-05-10T21:14:47.552Z [a12a] [stdout] Loaded GHCi configuration from /home/edka/.cache/stack/ghci-script/d4971f38/ghci-script
2024-05-10T21:14:47.552Z [a12a] Successfully started in 0.418 seconds.
tfausak commented 1 month ago

Huh, strange. I wonder why the initialization process think you have a custom interpreter set.

At any rate, I was going to suggest what you ended up doing. I'm glad it worked!

If you can think of a good way to determine when Purple Yolk should do stack ghci ${file} (as opposed to just stack ghci or ghci ${file}), I'd be happy to change the discovery mechanism.

EduardSergeev commented 1 month ago

Huh, strange. I wonder why the initialization process think you have a custom interpreter set.

To be perfectly honest I did have some non-empty (not default) values in some settings but I do not think I ever set them myself. I suspect those were set by some previous version of this extension (settings seem to persist even after corresponding extension is uninstalled). But when I reset them to the current default (empty) values I think I got the same behaviour.

If you can think of a good way to determine when Purple Yolk should do stack ghci ${file} (as opposed to just stack ghci or ghci ${file}), I'd be happy to change the discovery mechanism.

Well, ${file} option should probably always be passed if a single file (without workspace) is opened regardless of the interpreter type? Then if only Stack or only GHC(i) is installed on user's system the choice is simple: use whatever is installed (in my case I had only Stack). But if both Stack and GHC are installed launching GHCi probably makes more sense (since it is instantly available while Stack might need to download and install GHC before the ${file} can be loaded. Yet another option is to ask user which interpreter to use (in a similar way VSCode asks which debugger to use if multiple are installed)?

tfausak commented 1 month ago

I created #83 to improve opening single files with Stack.