diff --git a/cabal-install/src/Distribution/Client/CmdRepl.hs b/cabal-install/src/Distribution/Client/CmdRepl.hs index a8189f8e677..e243eb82974 100644 --- a/cabal-install/src/Distribution/Client/CmdRepl.hs +++ b/cabal-install/src/Distribution/Client/CmdRepl.hs @@ -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' $ @@ -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" ] diff --git a/cabal-testsuite/PackageTests/MultiRepl/EnabledClosure/cabal.test.hs b/cabal-testsuite/PackageTests/MultiRepl/EnabledClosure/cabal.test.hs index 54a0afeb91e..7bfea13c2bc 100644 --- a/cabal-testsuite/PackageTests/MultiRepl/EnabledClosure/cabal.test.hs +++ b/cabal-testsuite/PackageTests/MultiRepl/EnabledClosure/cabal.test.hs @@ -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 diff --git a/cabal-testsuite/PackageTests/MultiRepl/EnabledSucc/cabal.test.hs b/cabal-testsuite/PackageTests/MultiRepl/EnabledSucc/cabal.test.hs index 640b25d0d94..7ea2f71ea49 100644 --- a/cabal-testsuite/PackageTests/MultiRepl/EnabledSucc/cabal.test.hs +++ b/cabal-testsuite/PackageTests/MultiRepl/EnabledSucc/cabal.test.hs @@ -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 diff --git a/doc/internal/multi-repl.md b/doc/internal/multi-repl.md index 5f0f731e393..1e89872886a 100644 --- a/doc/internal/multi-repl.md +++ b/doc/internal/multi-repl.md @@ -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: ``` @@ -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