Skip to content

Commit

Permalink
Set the first multi-repl targets as the active unit
Browse files Browse the repository at this point in the history
When using the multi components repl, the last unit given to ghc
is the active unit. This change uses the cabal repl argument
order instead of relying on the 'listDirectory' ordering.
  • Loading branch information
TristanCacqueray authored and Mikolaj committed Jan 10, 2024
1 parent d9aa8b1 commit 0754feb
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 16 deletions.
21 changes: 20 additions & 1 deletion cabal-install/src/Distribution/Client/CmdRepl.hs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,25 @@ replAction flags@NixStyleFlags{extraFlags = r@ReplFlags{..}, ..} targetStrings g
-- unit files for components
unit_files <- listDirectory dir

-- Order the unit files so that the find target becomes the active unit
let active_unit_fp :: Maybe FilePath
active_unit_fp = do
-- Get the first target selectors from the cli
activeTarget <- safeHead targetSelectors
-- Lookup the targets :: Map UnitId [(ComponentTarget, NonEmpty TargetSelector)]
unitId <-
Map.toList targets
-- Keep the UnitId matching the desired target selector
& find (\(_, xs) -> any (\(_, selectors) -> activeTarget `elem` selectors) xs)
& fmap fst
-- Convert to filename (adapted from 'storePackageDirectory')
pure (prettyShow unitId)
unit_files_ordered :: [FilePath]
unit_files_ordered =
let (active_unit_files, other_units) = partition (\fp -> Just fp == active_unit_fp) unit_files
in -- GHC considers the last unit passed to be the active one
other_units ++ active_unit_files

-- run ghc --interactive with
runProgramInvocation verbosity $
programInvocation ghcProg' $
Expand All @@ -458,7 +477,7 @@ replAction flags@NixStyleFlags{extraFlags = r@ReplFlags{..}, ..} targetStrings g
, show (buildSettingNumJobs (buildSettings ctx))
]
: [ ["-unit", "@" ++ dir </> unit]
| unit <- unit_files
| unit <- unit_files_ordered
, unit /= "paths"
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@ main = do
skipUnlessGhcVersion ">= 9.4"
-- Note: only the last package is interactive.
-- this test should load pkg-b too.
res <- cabalWithStdin "v2-repl" ["--enable-multi-repl","pkg-a", "pkg-c"] ""

-- we should check that pkg-c is indeed loaded,
-- but currently the unit order is non-deterministic
-- Fix this when GHC has a way to change active unit.
-- TODO: ask for pkg-c unit, print Quu.quu
res <- cabalWithStdin "v2-repl" ["--enable-multi-repl","pkg-c", "pkg-a"] "Quu.quu"

assertOutputContains "- pkg-b-0 (interactive)" res
-- assertOutputContains "168" res
return ()
assertOutputContains "168" res
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,5 @@ main = do
cabalTest $ do
skipUnlessGhcVersion ">= 9.4"
skipIfWindows -- heisenbug, see #9103
-- the package order is non-deterministic.
-- add Bar.Bar input to test that packages are trully loaded
-- when GHC gets support for switching active units
res <- cabalWithStdin "v2-repl" ["--enable-multi-repl","pkg-a", "pkg-b"] ""
-- assertOutputContains "3735929054" res
return ()
res <- cabalWithStdin "v2-repl" ["--enable-multi-repl","pkg-b", "pkg-a"] "Bar.bar"
assertOutputContains "3735929054" res
11 changes: 10 additions & 1 deletion doc/internal/multi-repl.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ Here are some common targets which you can specify when using `cabal`.

* `all`: Build all the locally defined components.
* `exe:haskell-language-server`: Build the executable called `haskell-language-server`
* `lib:pkg-a lib:pkg-b`: Build the local libraries pkg-a and pkg-b.
* `lib:pkg-a lib:pkg-b`: Build the local libraries pkg-a and pkg-b. pkg-a will be the active unit.
* `src/Main.hs`: Build the unit which `src/Main.hs` belongs to.

After enabling multi-repl, passing a target specification to `cabal repl` which
resolves to multiple units will load all those units into a single repl session.
The first "target" will be the active unit.
For example:

```
Expand Down Expand Up @@ -203,6 +204,14 @@ At this time, the multi-repl is best used for interactive development situations
you want to use the repl to obtain fast-feedback about your project.
We have made sure that the multi-repl works with `ghcid` for example.

When evaluating code, make sure that the code is in the scope of the active unit,
which is the first target given on the command line. For example, to run the test suite
entrypoint, use:

```
ghcid --command "cabal repl --enable-multi-repl test:suite lib:pkg" --test Main.main
```

# Conclusion

Adding `cabal repl` support for multiple home units allows developers to easily
Expand Down

0 comments on commit 0754feb

Please sign in to comment.