From d022f8d5b68b5d8271908fa53887ab77092249bc Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Thu, 5 Oct 2023 12:50:18 -0700 Subject: [PATCH] Rename `ghcid-ng` to `ghciwatch` (#131) People get confused about `ghcid-ng`, and it's way too many syllables. `ghciwatch` is nice and descriptive, although if I add a `cabal build` backend it might be a little misleading again. Created with a handful of `sed` calls and a few file renames. --- .config/nextest.toml | 4 +- .github/workflows/release.yaml | 30 +++---- .github/workflows/version.yaml | 2 +- Cargo.lock | 2 +- Cargo.toml | 6 +- README.md | 10 +-- flake.nix | 24 +++--- nix/get-crate-version.nix | 4 +- nix/{ghcid-ng.nix => ghciwatch.nix} | 14 ++-- src/cli.rs | 10 +-- src/event_filter.rs | 2 +- src/ghci/mod.rs | 6 +- src/ghci/parse/eval.rs | 2 +- src/ghci/parse/show_paths.rs | 32 ++++---- src/lib.rs | 8 +- src/main.rs | 18 ++--- src/sync_sentinel.rs | 2 +- test-harness-macro/Cargo.toml | 2 +- test-harness-macro/src/lib.rs | 2 +- test-harness/Cargo.toml | 2 +- test-harness/src/fs.rs | 2 +- .../src/{ghcid_ng.rs => ghciwatch.rs} | 78 +++++++++---------- test-harness/src/internal.rs | 42 +++++----- test-harness/src/lib.rs | 10 +-- test-harness/src/matcher.rs | 14 ++-- test-harness/src/tracing_reader.rs | 2 +- tests/dot_ghci.rs | 8 +- tests/error_log.rs | 32 ++++---- tests/eval.rs | 42 +++++----- tests/failed_modules.rs | 16 ++-- tests/hooks.rs | 8 +- tests/load.rs | 20 ++--- tests/reload.rs | 28 +++---- tests/rename.rs | 14 ++-- tests/restart.rs | 26 +++---- tests/test.rs | 16 ++-- tests/watch_extension.rs | 12 +-- 37 files changed, 279 insertions(+), 273 deletions(-) rename nix/{ghcid-ng.nix => ghciwatch.nix} (91%) rename test-harness/src/{ghcid_ng.rs => ghciwatch.rs} (84%) diff --git a/.config/nextest.toml b/.config/nextest.toml index 4a1a778d..c0356c49 100644 --- a/.config/nextest.toml +++ b/.config/nextest.toml @@ -13,8 +13,8 @@ failure-output = "immediate-final" fail-fast = false [[profile.ci.overrides]] -# `kind(test)` means integration tests in the `../ghcid-ng/tests/` directory. +# `kind(test)` means integration tests in the `../tests/` directory. # https://nexte.st/book/filter-expressions.html#basic-predicates -filter = 'package(ghcid-ng) and kind(test)' +filter = 'package(ghciwatch) and kind(test)' platform = 'cfg(linux)' test-group = 'serial-integration' diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 688105e0..c228decd 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -93,9 +93,9 @@ jobs: - name: Create macOS universal executable if: runner.os == 'macOS' run: | - lipo -create -output target/release/ghcid-ng-macos \ - target/x86_64-apple-darwin/release/ghcid-ng \ - target/aarch64-apple-darwin/release/ghcid-ng + lipo -create -output target/release/ghciwatch-macos \ + target/x86_64-apple-darwin/release/ghciwatch \ + target/aarch64-apple-darwin/release/ghciwatch - uses: cachix/install-nix-action@v22 if: runner.os == 'Linux' @@ -113,21 +113,21 @@ jobs: if: runner.os == 'Linux' run: | mkdir -p target/ - RESULT=$(nix build --no-link --print-out-paths --print-build-logs .#ghcid-ng) - cp "$RESULT/bin/ghcid-ng" target/ghcid-ng-x86_64-linux + RESULT=$(nix build --no-link --print-out-paths --print-build-logs .#ghciwatch) + cp "$RESULT/bin/ghciwatch" target/ghciwatch-x86_64-linux - name: Build (Linux, aarch64) if: runner.os == 'Linux' run: | - RESULT=$(nix build --no-link --print-out-paths --print-build-logs .#ghcid-ng-aarch64-linux) - cp "$RESULT/bin/ghcid-ng" target/ghcid-ng-aarch64-linux + RESULT=$(nix build --no-link --print-out-paths --print-build-logs .#ghciwatch-aarch64-linux) + cp "$RESULT/bin/ghciwatch" target/ghciwatch-aarch64-linux - name: Upload macOS executable uses: actions/upload-artifact@v3 if: runner.os == 'macOS' with: name: macos - path: target/release/ghcid-ng-macos + path: target/release/ghciwatch-macos - name: Upload Linux executables uses: actions/upload-artifact@v3 @@ -135,8 +135,8 @@ jobs: with: name: linux path: | - target/ghcid-ng-x86_64-linux - target/ghcid-ng-aarch64-linux + target/ghciwatch-x86_64-linux + target/ghciwatch-aarch64-linux - name: Publish to crates.io if: runner.os == 'Linux' @@ -170,9 +170,9 @@ jobs: # - uses: actions/upload-artifact@v3 # with: # name: linux - # path: target/release/ghcid-ng-aarch64-linux + # path: target/release/ghciwatch-aarch64-linux # - # will be downloaded to `linux/ghcid-ng-aarch64-linux`. + # will be downloaded to `linux/ghciwatch-aarch64-linux`. uses: actions/download-artifact@v3 - name: Create release @@ -186,9 +186,9 @@ jobs: generate_release_notes: true tag_name: v${{ needs.version.outputs.version }} files: | - macos/ghcid-ng-macos - linux/ghcid-ng-x86_64-linux - linux/ghcid-ng-aarch64-linux + macos/ghciwatch-macos + linux/ghciwatch-x86_64-linux + linux/ghciwatch-aarch64-linux - name: Comment on PR with link to the release uses: peter-evans/create-or-update-comment@v2 diff --git a/.github/workflows/version.yaml b/.github/workflows/version.yaml index bd6ca0cc..a4d04680 100644 --- a/.github/workflows/version.yaml +++ b/.github/workflows/version.yaml @@ -5,7 +5,7 @@ # # Are you here because I left Mercury and now my personal access token is # invalid for workflows, breaking CI? You'll want to go to -# https://github.com/MercuryTechnologies/ghcid-ng/settings/secrets/actions +# https://github.com/MercuryTechnologies/ghciwatch/settings/secrets/actions # and update the `REPO_GITHUB_TOKEN` secret to a new, valid token. on: diff --git a/Cargo.lock b/Cargo.lock index 4e6d98b4..50bd644b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -547,7 +547,7 @@ dependencies = [ ] [[package]] -name = "ghcid-ng" +name = "ghciwatch" version = "0.3.7" dependencies = [ "aho-corasick", diff --git a/Cargo.toml b/Cargo.toml index 3605a834..b8d184be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ publish = false # Don't do `cargo publish`. # Define the root package: https://doc.rust-lang.org/cargo/reference/workspaces.html#root-package [package] -name = "ghcid-ng" +name = "ghciwatch" version = "0.3.7" edition = "2021" authors = [ @@ -24,8 +24,8 @@ authors = [ ] description = "ghci-based file watcher and recompiler for Haskell projects" readme = "README.md" -homepage = "https://github.com/MercuryTechnologies/ghcid-ng" -repository = "https://github.com/MercuryTechnologies/ghcid-ng" +homepage = "https://github.com/MercuryTechnologies/ghciwatch" +repository = "https://github.com/MercuryTechnologies/ghciwatch" license = "MIT" keywords = ["haskell", "ghci", "watchexec"] categories = ["command-line-utilities", "development-tools"] diff --git a/README.md b/README.md index 3837b833..207c4a77 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# ghcid-ng +# ghciwatch The next generation of [`ghcid`][ghcid], a [`ghci`][ghci]-based file watcher -and recompiler. `ghcid-ng` watches your modules for changes and reloads them in +and recompiler. `ghciwatch` watches your modules for changes and reloads them in a `ghci` session, displaying any errors. [ghcid]: https://github.com/ndmitchell/ghcid @@ -10,7 +10,7 @@ a `ghci` session, displaying any errors. ## Why a reimplementation? -When we started working on `ghcid-ng`, `ghcid` suffered from some significant +When we started working on `ghciwatch`, `ghcid` suffered from some significant limitations. In particular, `ghcid` couldn't deal with moved or deleted modules, and wouldn't detect new directories because it [can't easily update the set of files being watched at runtime.][ghcid-wait] We've also seen memory @@ -26,7 +26,7 @@ forward than making wide-spanning changes to an unfamiliar codebase. Rust makes it easy to ship static binaries. Rust also shares many features with Haskell: a [Hindley-Milner type system][hm] with inference, pattern matching, and immutability by default. Rust can also [interoperate with -Haskell][hs-bindgen], so in the future we'll be able to ship `ghcid-ng` as a +Haskell][hs-bindgen], so in the future we'll be able to ship `ghciwatch` as a Hackage package natively. Finally, Rust is home to the excellent cross-platform and battle-tested [`watchexec`][watchexec] library, used to implement the `watchexec` binary and `cargo-watch`, which solves a lot of the thorny problems @@ -42,7 +42,7 @@ of watching files for us. Recompiling a project when files change is a fairly common development task, so there's a bunch of tools with this same rough goal. In particular, [`watchexec`][watchexec] is a nice off-the-shelf solution. Why not just run -`watchexec -e hs cabal build`? In truth, `ghcid-ng` doesn't just recompile the +`watchexec -e hs cabal build`? In truth, `ghciwatch` doesn't just recompile the project when it detects changes. It instead manages an interactive `ghci` session, instructing it to reload modules when relevant. This involves a fairly complex dance of communicating to `ghci` over stdin and parsing its stdout, so diff --git a/flake.nix b/flake.nix index 2397ff64..e0369620 100644 --- a/flake.nix +++ b/flake.nix @@ -74,8 +74,8 @@ pkgs = makePkgs {}; - make-ghcid-ng = pkgs: - pkgs.callPackage ./nix/ghcid-ng.nix {} { + make-ghciwatch = pkgs: + pkgs.callPackage ./nix/ghciwatch.nix {} { # GHC versions to include in the environment for integration tests. # Keep this in sync with `./test-harness/src/ghc_version.rs`. ghcVersions = [ @@ -86,15 +86,15 @@ ]; }; - ghcid-ng = make-ghcid-ng pkgs; + ghciwatch = make-ghciwatch pkgs; in { - inherit (ghcid-ng) checks; + inherit (ghciwatch) checks; packages = { - inherit ghcid-ng; - default = ghcid-ng; - ghcid-ng-tests = ghcid-ng.checks.ghcid-ng-tests; + inherit ghciwatch; + default = ghciwatch; + ghciwatch-tests = ghciwatch.checks.ghciwatch-tests; get-crate-version = pkgs.callPackage ./nix/get-crate-version.nix {}; make-release-commit = pkgs.callPackage ./nix/make-release-commit.nix {}; @@ -109,17 +109,17 @@ }; } // (pkgs.lib.optionalAttrs pkgs.stdenv.isLinux { - # ghcid-ng cross-compiled to aarch64-linux. - ghcid-ng-aarch64-linux = let + # ghciwatch cross-compiled to aarch64-linux. + ghciwatch-aarch64-linux = let crossPkgs = makePkgs {crossSystem = "aarch64-linux";}; in - (make-ghcid-ng crossPkgs).overrideAttrs (old: { + (make-ghciwatch crossPkgs).overrideAttrs (old: { CARGO_BUILD_TARGET = "aarch64-unknown-linux-musl"; CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER = "${crossPkgs.stdenv.cc.targetPrefix}cc"; }); }); - apps.default = flake-utils.lib.mkApp {drv = ghcid-ng;}; + apps.default = flake-utils.lib.mkApp {drv = ghciwatch;}; devShells.default = pkgs.craneLib.devShell { checks = self.checks.${localSystem}; @@ -128,7 +128,7 @@ RUST_SRC_PATH = pkgs.rustPlatform.rustLibSrc; # Provide GHC versions to use to the integration test suite. - inherit (ghcid-ng) GHC_VERSIONS; + inherit (ghciwatch) GHC_VERSIONS; # Extra development tools (cargo and rustc are included by default). packages = [ diff --git a/nix/get-crate-version.nix b/nix/get-crate-version.nix index c2371edd..28437d5f 100644 --- a/nix/get-crate-version.nix +++ b/nix/get-crate-version.nix @@ -12,11 +12,11 @@ writeShellApplication { ]; text = '' - # Gets the version of `ghcid-ng` in `Cargo.toml` using + # Gets the version of `ghciwatch` in `Cargo.toml` using # `cargo metadata` and `jq`. VERSION=$(cargo metadata --format-version 1 \ - | jq -r '.packages[] | select(.name == "ghcid-ng") | .version') + | jq -r '.packages[] | select(.name == "ghciwatch") | .version') echo "Version in \`Cargo.toml\` is $VERSION" 1>&2 diff --git a/nix/ghcid-ng.nix b/nix/ghciwatch.nix similarity index 91% rename from nix/ghcid-ng.nix rename to nix/ghciwatch.nix index 57d555e9..e830ad11 100644 --- a/nix/ghcid-ng.nix +++ b/nix/ghciwatch.nix @@ -85,7 +85,7 @@ }; checks = { - ghcid-ng-tests = craneLib.cargoNextest (commonArgs + ghciwatch-tests = craneLib.cargoNextest (commonArgs // { buildInputs = (commonArgs.buildInputs or []) ++ ghcBuildInputs; NEXTEST_PROFILE = "ci"; @@ -94,18 +94,18 @@ # Provide GHC versions to use to the integration test suite. inherit GHC_VERSIONS; }); - ghcid-ng-clippy = craneLib.cargoClippy (commonArgs + ghciwatch-clippy = craneLib.cargoClippy (commonArgs // { cargoClippyExtraArgs = "--all-targets -- --deny warnings"; inherit GHC_VERSIONS; }); - ghcid-ng-doc = craneLib.cargoDoc (commonArgs + ghciwatch-doc = craneLib.cargoDoc (commonArgs // { cargoDocExtraArgs = "--document-private-items"; RUSTDOCFLAGS = "-D warnings"; }); - ghcid-ng-fmt = craneLib.cargoFmt commonArgs; - ghcid-ng-audit = craneLib.cargoAudit (commonArgs + ghciwatch-fmt = craneLib.cargoFmt commonArgs; + ghciwatch-audit = craneLib.cargoAudit (commonArgs // { inherit advisory-db; }); @@ -140,11 +140,11 @@ in craneLib.buildPackage (commonArgs // { # Don't run tests; we'll do that in a separate derivation. - # This will allow people to install and depend on `ghcid-ng` + # This will allow people to install and depend on `ghciwatch` # without downloading a half dozen different versions of GHC. doCheck = false; - # Only build `ghcid-ng`, not the test macros. + # Only build `ghciwatch`, not the test macros. cargoBuildCommand = "cargoWithProfile build"; passthru = { diff --git a/src/cli.rs b/src/cli.rs index 25c8744f..5297257a 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -21,7 +21,7 @@ use crate::normal_path::NormalPath; pub struct Opts { /// A shell command which starts a `ghci` REPL, e.g. `ghci` or `cabal v2-repl` or similar. /// - /// This is used to launch the underlying `ghci` session that `ghcid-ng` controls. + /// This is used to launch the underlying `ghci` session that `ghciwatch` controls. /// /// May contain quoted arguments which will be parsed in a `sh`-like manner. #[arg(long, value_name = "SHELL_COMMAND")] @@ -111,8 +111,8 @@ pub struct LoggingOpts { /// /// See: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html /// - /// A nice value is "ghcid_ng=debug". - #[arg(long, default_value = "ghcid_ng=info")] + /// A nice value is "ghciwatch=debug". + #[arg(long, default_value = "ghciwatch=info")] pub tracing_filter: String, /// How to display backtraces in error messages. @@ -137,7 +137,7 @@ pub struct LoggingOpts { /// Lifecycle hooks. /// -/// These are commands (mostly `ghci` commands) to run at various points in the `ghcid-ng` +/// These are commands (mostly `ghci` commands) to run at various points in the `ghciwatch` /// lifecycle. #[derive(Debug, Clone, clap::Args)] #[clap(next_help_heading = "Lifecycle hooks")] @@ -184,7 +184,7 @@ pub struct HookOpts { /// `ghci` commands to run after restarting `ghci`. /// Can be given multiple times. /// - /// `ghci` cannot reload after files are deleted due to a bug, so `ghcid-ng` has to restart the + /// `ghci` cannot reload after files are deleted due to a bug, so `ghciwatch` has to restart the /// underlying `ghci` session when this happens. Note that the `--before-restart-ghci` and /// `--after-restart-ghci` commands will therefore run in different `ghci` sessions without /// shared context. diff --git a/src/event_filter.rs b/src/event_filter.rs index 10a6f7ff..c760519d 100644 --- a/src/event_filter.rs +++ b/src/event_filter.rs @@ -1,4 +1,4 @@ -//! Parsing [`watchexec::event::Event`]s into changes `ghcid-ng` can respond to. +//! Parsing [`watchexec::event::Event`]s into changes `ghciwatch` can respond to. use std::collections::HashMap; diff --git a/src/ghci/mod.rs b/src/ghci/mod.rs index ba66256e..83ffffb4 100644 --- a/src/ghci/mod.rs +++ b/src/ghci/mod.rs @@ -64,12 +64,12 @@ use self::parse::parse_eval_commands; /// The `ghci` prompt we use. Should be unique enough, but maybe we can make it better with Unicode /// private-use-area codepoints or something in the future. -pub const PROMPT: &str = "###~GHCID-NG-PROMPT~###"; +pub const PROMPT: &str = "###~GHCIWATCH-PROMPT~###"; /// The name we import `System.IO` as in `ghci`. This is used to run a few `putStrLn` commands and /// similar without messing with the user's namespace. If you have a module in your project named -/// `GHCID_NG_IO_INTERNAL__` that's on you. -pub const IO_MODULE_NAME: &str = "GHCID_NG_IO_INTERNAL__"; +/// `GHCIWATCH_IO_INTERNAL__` that's on you. +pub const IO_MODULE_NAME: &str = "GHCIWATCH_IO_INTERNAL__"; /// Options for constructing a [`Ghci`]. This is like a lower-effort builder interface, mostly provided /// because Rust tragically lacks named arguments. diff --git a/src/ghci/parse/eval.rs b/src/ghci/parse/eval.rs index 8be528a0..2657e056 100644 --- a/src/ghci/parse/eval.rs +++ b/src/ghci/parse/eval.rs @@ -20,7 +20,7 @@ use crate::ghci::GhciCommand; use super::lines::rest_of_line; use super::lines::until_newline; -/// A (Haskell) command for `ghcid-ng` to evaluate in `ghci`. +/// A (Haskell) command for `ghciwatch` to evaluate in `ghci`. #[derive(Debug, Clone, PartialEq, Eq)] pub struct EvalCommand { /// The Haskell code or `ghci` command to evaluate. diff --git a/src/ghci/parse/show_paths.rs b/src/ghci/parse/show_paths.rs index 862776c7..23356023 100644 --- a/src/ghci/parse/show_paths.rs +++ b/src/ghci/parse/show_paths.rs @@ -161,24 +161,24 @@ mod tests { .parse(indoc!( " current working directory: - /Users/wiggles/ghcid-ng/ghcid-ng/tests/data/simple + /Users/wiggles/ghciwatch/ghciwatch/tests/data/simple module import search paths: - /Users/wiggles/ghcid-ng/ghcid-ng/tests/data/simple/dist-newstyle/build/aarch64-osx/ghc-9.0.2/my-simple-package-0.1.0.0/l/test-dev/build/test-dev + /Users/wiggles/ghciwatch/ghciwatch/tests/data/simple/dist-newstyle/build/aarch64-osx/ghc-9.0.2/my-simple-package-0.1.0.0/l/test-dev/build/test-dev test src - /Users/wiggles/ghcid-ng/ghcid-ng/tests/data/simple/dist-newstyle/build/aarch64-osx/ghc-9.0.2/my-simple-package-0.1.0.0/l/test-dev/build/test-dev/autogen - /Users/wiggles/ghcid-ng/ghcid-ng/tests/data/simple/dist-newstyle/build/aarch64-osx/ghc-9.0.2/my-simple-package-0.1.0.0/l/test-dev/build/global-autogen + /Users/wiggles/ghciwatch/ghciwatch/tests/data/simple/dist-newstyle/build/aarch64-osx/ghc-9.0.2/my-simple-package-0.1.0.0/l/test-dev/build/test-dev/autogen + /Users/wiggles/ghciwatch/ghciwatch/tests/data/simple/dist-newstyle/build/aarch64-osx/ghc-9.0.2/my-simple-package-0.1.0.0/l/test-dev/build/global-autogen " )) .unwrap(), ShowPaths { - cwd: Utf8PathBuf::from("/Users/wiggles/ghcid-ng/ghcid-ng/tests/data/simple"), + cwd: Utf8PathBuf::from("/Users/wiggles/ghciwatch/ghciwatch/tests/data/simple"), search_paths: vec![ - Utf8PathBuf::from("/Users/wiggles/ghcid-ng/ghcid-ng/tests/data/simple/dist-newstyle/build/aarch64-osx/ghc-9.0.2/my-simple-package-0.1.0.0/l/test-dev/build/test-dev"), - Utf8PathBuf::from("/Users/wiggles/ghcid-ng/ghcid-ng/tests/data/simple/test"), - Utf8PathBuf::from("/Users/wiggles/ghcid-ng/ghcid-ng/tests/data/simple/src"), - Utf8PathBuf::from("/Users/wiggles/ghcid-ng/ghcid-ng/tests/data/simple/dist-newstyle/build/aarch64-osx/ghc-9.0.2/my-simple-package-0.1.0.0/l/test-dev/build/test-dev/autogen"), - Utf8PathBuf::from("/Users/wiggles/ghcid-ng/ghcid-ng/tests/data/simple/dist-newstyle/build/aarch64-osx/ghc-9.0.2/my-simple-package-0.1.0.0/l/test-dev/build/global-autogen"), + Utf8PathBuf::from("/Users/wiggles/ghciwatch/ghciwatch/tests/data/simple/dist-newstyle/build/aarch64-osx/ghc-9.0.2/my-simple-package-0.1.0.0/l/test-dev/build/test-dev"), + Utf8PathBuf::from("/Users/wiggles/ghciwatch/ghciwatch/tests/data/simple/test"), + Utf8PathBuf::from("/Users/wiggles/ghciwatch/ghciwatch/tests/data/simple/src"), + Utf8PathBuf::from("/Users/wiggles/ghciwatch/ghciwatch/tests/data/simple/dist-newstyle/build/aarch64-osx/ghc-9.0.2/my-simple-package-0.1.0.0/l/test-dev/build/test-dev/autogen"), + Utf8PathBuf::from("/Users/wiggles/ghciwatch/ghciwatch/tests/data/simple/dist-newstyle/build/aarch64-osx/ghc-9.0.2/my-simple-package-0.1.0.0/l/test-dev/build/global-autogen"), ], } ); @@ -188,13 +188,13 @@ mod tests { .parse(indoc!( " current working directory: - /Users/wiggles/ghcid-ng/ghcid-ng/tests/data/simple + /Users/wiggles/ghciwatch/ghciwatch/tests/data/simple module import search paths: none " )) .unwrap(), ShowPaths { - cwd: Utf8PathBuf::from("/Users/wiggles/ghcid-ng/ghcid-ng/tests/data/simple"), + cwd: Utf8PathBuf::from("/Users/wiggles/ghciwatch/ghciwatch/tests/data/simple"), search_paths: vec![], } ); @@ -205,7 +205,7 @@ mod tests { .parse(indoc!( " current working directory: - /Users/wiggles/ghcid-ng/ghcid-ng/tests/data/simple + /Users/wiggles/ghciwatch/ghciwatch/tests/data/simple module import search paths: none /Foo/bar " @@ -217,7 +217,7 @@ mod tests { .parse(indoc!( " current working directory: - /Users/wiggles/ghcid-ng/ghcid-ng/tests/data/simple + /Users/wiggles/ghciwatch/ghciwatch/tests/data/simple module import search paths: /Foo/bar /Foo/bar @@ -229,13 +229,13 @@ mod tests { #[test] fn test_path_to_module() { let paths = ShowPaths { - cwd: Utf8PathBuf::from("/Users/wiggles/ghcid-ng/"), + cwd: Utf8PathBuf::from("/Users/wiggles/ghciwatch/"), search_paths: vec![], }; assert_eq!( paths - .path_to_module(Utf8Path::new("/Users/wiggles/ghcid-ng/Foo/Bar/Baz.hs")) + .path_to_module(Utf8Path::new("/Users/wiggles/ghciwatch/Foo/Bar/Baz.hs")) .unwrap(), "Foo.Bar.Baz" ); diff --git a/src/lib.rs b/src/lib.rs index 99e20115..164e8195 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,12 @@ -//! `ghcid-ng` is a `ghci`-based file watcher and recompiler for Haskell projects, leveraging +//! `ghciwatch` is a `ghci`-based file watcher and recompiler for Haskell projects, leveraging //! Haskell's interpreted mode for faster reloads. //! -//! `ghcid-ng` watches your modules for changes and reloads them in a `ghci` session, displaying +//! `ghciwatch` watches your modules for changes and reloads them in a `ghci` session, displaying //! any errors. //! -//! Note that the `ghcid-ng` Rust library is a convenience and shouldn't be depended on. I do not +//! Note that the `ghciwatch` Rust library is a convenience and shouldn't be depended on. I do not //! consider this to be a public/stable API and will make breaking changes here in minor version -//! bumps. If you'd like a stable `ghcid-ng` Rust API for some reason, let me know and we can maybe +//! bumps. If you'd like a stable `ghciwatch` Rust API for some reason, let me know and we can maybe //! work something out. #![deny(missing_docs)] diff --git a/src/main.rs b/src/main.rs index 88c48bf2..febe8b84 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,16 @@ -//! `ghcid-ng` is a `ghci`-based file watcher and recompiler for Haskell projects, leveraging +//! `ghciwatch` is a `ghci`-based file watcher and recompiler for Haskell projects, leveraging //! Haskell's interpreted mode for faster reloads. //! -//! `ghcid-ng` watches your modules for changes and reloads them in a `ghci` session, displaying +//! `ghciwatch` watches your modules for changes and reloads them in a `ghci` session, displaying //! any errors. use clap::Parser; -use ghcid_ng::cli; -use ghcid_ng::Ghci; -use ghcid_ng::GhciOpts; -use ghcid_ng::TracingOpts; -use ghcid_ng::Watcher; -use ghcid_ng::WatcherOpts; +use ghciwatch::cli; +use ghciwatch::Ghci; +use ghciwatch::GhciOpts; +use ghciwatch::TracingOpts; +use ghciwatch::Watcher; +use ghciwatch::WatcherOpts; use miette::IntoDiagnostic; use miette::WrapErr; @@ -22,7 +22,7 @@ async fn main() -> miette::Result<()> { TracingOpts::from_cli(&opts).install()?; ::tracing::warn!( - "This is a prerelease alpha version of `ghcid-ng`! Expect a rough user experience, and please report bugs or other issues to the #mighty-dux channel on Slack." + "This is a prerelease alpha version of `ghciwatch`! Expect a rough user experience, and please report bugs or other issues to the #mighty-dux channel on Slack." ); let ghci = Ghci::new(GhciOpts::from_cli(&opts)?) diff --git a/src/sync_sentinel.rs b/src/sync_sentinel.rs index f04cb58d..f6cd7a40 100644 --- a/src/sync_sentinel.rs +++ b/src/sync_sentinel.rs @@ -45,7 +45,7 @@ impl SyncSentinel { impl Display for SyncSentinel { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "###~GHCID-NG-SYNC-{}~###", self.id) + write!(f, "###~GHCIWATCH-SYNC-{}~###", self.id) } } diff --git a/test-harness-macro/Cargo.toml b/test-harness-macro/Cargo.toml index acc522f1..fb4c0126 100644 --- a/test-harness-macro/Cargo.toml +++ b/test-harness-macro/Cargo.toml @@ -3,7 +3,7 @@ name = "test-harness-macro" version = "0.1.0" edition = "2021" -description = "Test attribute for ghcid-ng" +description = "Test attribute for ghciwatch" publish = false diff --git a/test-harness-macro/src/lib.rs b/test-harness-macro/src/lib.rs index db59c6a3..e9945223 100644 --- a/test-harness-macro/src/lib.rs +++ b/test-harness-macro/src/lib.rs @@ -1,4 +1,4 @@ -//! `#[test]` attribute macro for `ghcid-ng` integration tests. +//! `#[test]` attribute macro for `ghciwatch` integration tests. #![deny(missing_docs)] #![deny(rustdoc::broken_intra_doc_links)] diff --git a/test-harness/Cargo.toml b/test-harness/Cargo.toml index 32e43cda..f2828228 100644 --- a/test-harness/Cargo.toml +++ b/test-harness/Cargo.toml @@ -2,7 +2,7 @@ name = "test-harness" version = "0.1.0" edition = "2021" -description = "Test harness for ghcid-ng" +description = "Test harness for ghciwatch" publish = false [dependencies] diff --git a/test-harness/src/fs.rs b/test-harness/src/fs.rs index fd7aa780..297bcbe3 100644 --- a/test-harness/src/fs.rs +++ b/test-harness/src/fs.rs @@ -1,4 +1,4 @@ -//! Filesystem utilities for writing integration tests for `ghcid-ng`. +//! Filesystem utilities for writing integration tests for `ghciwatch`. use std::fmt::Debug; use std::path::Path; diff --git a/test-harness/src/ghcid_ng.rs b/test-harness/src/ghciwatch.rs similarity index 84% rename from test-harness/src/ghcid_ng.rs rename to test-harness/src/ghciwatch.rs index 334964f7..12201c70 100644 --- a/test-harness/src/ghcid_ng.rs +++ b/test-harness/src/ghciwatch.rs @@ -18,20 +18,20 @@ use crate::GhcVersion; use crate::IntoMatcher; use crate::Matcher; -/// Where to write `ghcid-ng` logs written by integration tests, relative to the temporary +/// Where to write `ghciwatch` logs written by integration tests, relative to the temporary /// directory created for the test. -pub(crate) const LOG_FILENAME: &str = "ghcid-ng.json"; +pub(crate) const LOG_FILENAME: &str = "ghciwatch.json"; -/// Builder for [`GhcidNg`]. -pub struct GhcidNgBuilder { +/// Builder for [`GhciWatch`]. +pub struct GhciWatchBuilder { project_directory: PathBuf, args: Vec, #[allow(clippy::type_complexity)] before_start: Option BoxFuture<'static, miette::Result<()>> + Send>>, } -impl GhcidNgBuilder { - /// Create a new builder for a `ghcid-ng` session with the given project directory. +impl GhciWatchBuilder { + /// Create a new builder for a `ghciwatch` session with the given project directory. pub fn new(project_directory: impl AsRef) -> Self { Self { project_directory: project_directory.as_ref().to_owned(), @@ -40,13 +40,13 @@ impl GhcidNgBuilder { } } - /// Add an argument to the `ghcid-ng` invocation. + /// Add an argument to the `ghciwatch` invocation. pub fn with_arg(mut self, arg: impl AsRef) -> Self { self.args.push(arg.as_ref().to_owned()); self } - /// Add multiple arguments to the `ghcid-ng` invocation. + /// Add multiple arguments to the `ghciwatch` invocation. pub fn with_args(mut self, args: impl IntoIterator>) -> Self { self.args .extend(args.into_iter().map(|s| s.as_ref().to_owned())); @@ -54,7 +54,7 @@ impl GhcidNgBuilder { } /// Add a hook to run after project files are copied to the temporary directory but before - /// `ghcid-ng` is started. + /// `ghciwatch` is started. pub fn before_start(mut self, before_start: impl Fn(PathBuf) -> F + Send + 'static) -> Self where F: Future> + Send + 'static, @@ -63,27 +63,27 @@ impl GhcidNgBuilder { self } - /// Start `ghcid-ng`. - pub async fn start(self) -> miette::Result { - GhcidNg::from_builder(self).await + /// Start `ghciwatch`. + pub async fn start(self) -> miette::Result { + GhciWatch::from_builder(self).await } } -/// `ghcid-ng` session for integration testing. +/// `ghciwatch` session for integration testing. /// -/// This handles copying a directory of files to a temporary directory, starting a `ghcid-ng` +/// This handles copying a directory of files to a temporary directory, starting a `ghciwatch` /// session, and asynchronously reading a stream of log events from its JSON log output. -pub struct GhcidNg { - /// The current working directory of the `ghcid-ng` session. +pub struct GhciWatch { + /// The current working directory of the `ghciwatch` session. cwd: PathBuf, - /// A stream of tracing events from `ghcid-ng`. + /// A stream of tracing events from `ghciwatch`. tracing_reader: TracingReader, /// The major version of GHC this test is running under. ghc_version: GhcVersion, } -impl GhcidNg { - async fn from_builder(mut builder: GhcidNgBuilder) -> miette::Result { +impl GhciWatch { + async fn from_builder(mut builder: GhciWatchBuilder) -> miette::Result { let full_ghc_version = crate::internal::get_ghc_version()?; let ghc_version = full_ghc_version.parse()?; let tempdir = crate::internal::set_tempdir()?; @@ -111,8 +111,8 @@ impl GhcidNg { let log_path = tempdir.join(LOG_FILENAME); - tracing::info!("Starting ghcid-ng"); - let mut command = Command::new(test_bin::get_test_bin("ghcid-ng").get_program()); + tracing::info!("Starting ghciwatch"); + let mut command = Command::new(test_bin::get_test_bin("ghciwatch").get_program()); command .arg("--log-json") .arg(&log_path) @@ -125,8 +125,8 @@ impl GhcidNg { "hpack --force .", "--tracing-filter", &[ - "ghcid_ng::watcher=trace", - "ghcid_ng=debug", + "ghciwatch::watcher=trace", + "ghciwatch=debug", "watchexec=debug", "watchexec::fs=trace", ].join(","), @@ -150,31 +150,31 @@ impl GhcidNg { let mut child = command .spawn() .into_diagnostic() - .wrap_err("Failed to start `ghcid-ng`")?; + .wrap_err("Failed to start `ghciwatch`")?; - // Wait for `ghcid-ng` to create the `log_path` + // Wait for `ghciwatch` to create the `log_path` let creates_log_path = tokio::time::timeout(Duration::from_secs(10), crate::fs::wait_for_path(&log_path)); tokio::select! { child_result = child.wait() => { return match child_result { Err(err) => { - Err(err).into_diagnostic().wrap_err("ghcid-ng failed to execute") + Err(err).into_diagnostic().wrap_err("ghciwatch failed to execute") } Ok(status) => { - Err(miette!("ghcid-ng exited: {status}")) + Err(miette!("ghciwatch exited: {status}")) } } } log_path_result = creates_log_path => { if log_path_result.is_err() { - return Err(miette!("`ghcid-ng` didn't create log path {log_path:?} fast enough")); + return Err(miette!("`ghciwatch` didn't create log path {log_path:?} fast enough")); } } else => {} } - crate::internal::set_ghcid_ng_process(child)?; + crate::internal::set_ghciwatch_process(child)?; let tracing_reader = TracingReader::new(log_path.clone()).await?; @@ -185,9 +185,9 @@ impl GhcidNg { }) } - /// Start a new `ghcid-ng` session in a copy of the given path. + /// Start a new `ghciwatch` session in a copy of the given path. pub async fn new(project_directory: impl AsRef) -> miette::Result { - GhcidNgBuilder::new(project_directory).start().await + GhciWatchBuilder::new(project_directory).start().await } /// Wait until a matching log event is found. @@ -255,7 +255,7 @@ impl GhcidNg { .await } - /// Wait until `ghcid-ng` completes its initial load. + /// Wait until `ghciwatch` completes its initial load. pub async fn wait_until_started(&mut self) -> miette::Result { self.assert_logged_with_timeout( None, @@ -263,10 +263,10 @@ impl GhcidNg { Duration::from_secs(60), ) .await - .wrap_err("ghcid-ng didn't start in time") + .wrap_err("ghciwatch didn't start in time") } - /// Wait until `ghcid-ng` is ready to receive file events. + /// Wait until `ghciwatch` is ready to receive file events. pub async fn wait_until_watcher_started(&mut self) -> miette::Result { // Only _after_ `ghci` starts up do we initialize the file watcher. // `watchexec` sends a few events when it starts up: @@ -293,20 +293,20 @@ impl GhcidNg { .wrap_err("watchexec filesystem worker didn't start in time") } - /// Wait until `ghcid-ng` completes its initial load and is ready to receive file events. + /// Wait until `ghciwatch` completes its initial load and is ready to receive file events. pub async fn wait_until_ready(&mut self) -> miette::Result<()> { self.wait_until_started().await?; self.wait_until_watcher_started().await?; Ok(()) } - /// Wait until `ghcid-ng` reloads the `ghci` session due to changed modules. + /// Wait until `ghciwatch` reloads the `ghci` session due to changed modules. pub async fn wait_until_reload(&mut self) -> miette::Result<()> { // TODO: It would be nice to verify which modules are changed. self.assert_logged("^Reloading ghci:\n").await.map(|_| ()) } - /// Wait until `ghcid-ng` adds new modules to the `ghci` session. + /// Wait until `ghciwatch` adds new modules to the `ghci` session. pub async fn wait_until_add(&mut self) -> miette::Result<()> { // TODO: It would be nice to verify which modules are being added. self.assert_logged("^Adding modules to ghci:\n") @@ -314,7 +314,7 @@ impl GhcidNg { .map(|_| ()) } - /// Wait until `ghcid-ng` restarts the `ghci` session. + /// Wait until `ghciwatch` restarts the `ghci` session. pub async fn wait_until_restart(&mut self) -> miette::Result<()> { // TODO: It would be nice to verify which modules have been deleted/moved. self.assert_logged("^Restarting ghci:\n").await.map(|_| ()) @@ -347,7 +347,7 @@ async fn write_cabal_config(home: &Path) -> miette::Result<()> { /// Check that `ghc-{ghc_version} --version` executes successfully. /// /// This is a nice check that the given GHC version is present in the environment, to fail tests -/// early without waiting for `ghcid-ng` to fail. +/// early without waiting for `ghciwatch` to fail. async fn check_ghc_version(home: &Path, ghc_version: &str) -> miette::Result<()> { let _output = Command::new(format!("ghc-{ghc_version}")) .env("HOME", home) diff --git a/test-harness/src/internal.rs b/test-harness/src/internal.rs index c422b332..2d5c6a97 100644 --- a/test-harness/src/internal.rs +++ b/test-harness/src/internal.rs @@ -14,7 +14,7 @@ use nix::unistd::Pid; use tokio::process::Child; thread_local! { - /// The temporary directory where `ghcid-ng` is run. Note that because tests are run with the + /// The temporary directory where `ghciwatch` is run. Note that because tests are run with the /// `tokio` current-thread runtime, this is unique per-test. pub(crate) static TEMPDIR: RefCell> = RefCell::new(None); @@ -22,20 +22,20 @@ thread_local! { /// This is used to select the correct GHC version to run. pub(crate) static GHC_VERSION: RefCell = RefCell::new(String::new()); - /// The `ghcid-ng` process for this test. + /// The `ghciwatch` process for this test. /// /// This is set so that we can make sure to kill it when the test ends. - pub(crate) static GHCID_NG_PROCESS: RefCell> = RefCell::new(None); + pub(crate) static GHCIWATCH_PROCESS: RefCell> = RefCell::new(None); } /// Wraps an asynchronous test with startup/cleanup code. /// /// Before the user test code, we set the [`GHC_VERSION`] thread-local variable so that when -/// we construct a [`super::GhcidNg`] it can use the correct GHC version. +/// we construct a [`super::GhciWatch`] it can use the correct GHC version. /// /// Then we run the user test code. If it errors, we save the logs to `CARGO_TARGET_TMPDIR`. /// -/// Finally, we wait for the [`GHCID_NG_PROCESS`] to exit and clean up the temporary directory `GhcidNg` +/// Finally, we wait for the [`GHCIWATCH_PROCESS`] to exit and clean up the temporary directory `GhciWatch` /// created. pub async fn wrap_test( test: impl Future + Send + 'static, @@ -77,7 +77,7 @@ fn save_test_logs(test_name: String, cargo_target_tmpdir: PathBuf) { tempdir .borrow() .as_deref() - .map(|path| path.join(crate::ghcid_ng::LOG_FILENAME)) + .map(|path| path.join(crate::ghciwatch::LOG_FILENAME)) .expect("`test_harness::TEMPDIR` is not set") }); @@ -100,29 +100,29 @@ fn save_test_logs(test_name: String, cargo_target_tmpdir: PathBuf) { /// Perform end-of-test cleanup. /// -/// 1. Kill the [`GHCID_NG_PROCESS`]. +/// 1. Kill the [`GHCIWATCH_PROCESS`]. /// 2. Remove the [`TEMPDIR`] from the filesystem. async fn cleanup() { - let child = GHCID_NG_PROCESS.with(|child| child.take()); + let child = GHCIWATCH_PROCESS.with(|child| child.take()); match child { None => { - panic!("`GHCID_NG_PROCESS` is not set"); + panic!("`GHCIWATCH_PROCESS` is not set"); } Some(mut child) => { - send_signal(&child, Signal::SIGINT).expect("Failed to send SIGINT to `ghcid-ng`"); + send_signal(&child, Signal::SIGINT).expect("Failed to send SIGINT to `ghciwatch`"); match tokio::time::timeout(Duration::from_secs(10), child.wait()).await { Err(_) => { - tracing::info!("ghcid-ng didn't exit in time, killing"); + tracing::info!("ghciwatch didn't exit in time, killing"); child .kill() .await - .expect("Failed to kill `ghcid-ng` after test completion"); + .expect("Failed to kill `ghciwatch` after test completion"); } Ok(Ok(status)) => { - tracing::info!(%status, "ghcid-ng exited"); + tracing::info!(%status, "ghciwatch exited"); } Ok(Err(err)) => { - tracing::error!("Waiting for ghcid-ng to exit failed: {err}"); + tracing::error!("Waiting for ghciwatch to exit failed: {err}"); } } } @@ -161,7 +161,7 @@ pub(crate) fn get_ghc_version() -> miette::Result { let ghc_version = GHC_VERSION.with(|version| version.borrow().to_owned()); if ghc_version.is_empty() { Err(miette!("`GHC_VERSION` is not set")) - .wrap_err("`GhcidNg` can only be used in `#[test_harness::test]` functions") + .wrap_err("`GhciWatch` can only be used in `#[test_harness::test]` functions") } else { Ok(ghc_version) } @@ -179,7 +179,7 @@ pub(crate) fn set_tempdir() -> miette::Result { TEMPDIR.with(|thread_tempdir| { if thread_tempdir.borrow().is_some() { return Err(miette!( - "`GhcidNg` can only be constructed once per `#[test_harness::test]` function" + "`GhciWatch` can only be constructed once per `#[test_harness::test]` function" )); } *thread_tempdir.borrow_mut() = Some(tempdir.path().to_path_buf()); @@ -190,14 +190,14 @@ pub(crate) fn set_tempdir() -> miette::Result { Ok(tempdir.into_path()) } -/// Set [`GHCID_NG_PROCESS`] to the given [`Child`]. +/// Set [`GHCIWATCH_PROCESS`] to the given [`Child`]. /// -/// Fails if [`GHCID_NG_PROCESS`] is already set. -pub(crate) fn set_ghcid_ng_process(child: Child) -> miette::Result<()> { - GHCID_NG_PROCESS.with(|maybe_child| { +/// Fails if [`GHCIWATCH_PROCESS`] is already set. +pub(crate) fn set_ghciwatch_process(child: Child) -> miette::Result<()> { + GHCIWATCH_PROCESS.with(|maybe_child| { if maybe_child.borrow().is_some() { return Err(miette!( - "`GhcidNg` can only be constructed once per `#[test_harness::test]` function" + "`GhciWatch` can only be constructed once per `#[test_harness::test]` function" )); } diff --git a/test-harness/src/lib.rs b/test-harness/src/lib.rs index 43793035..45cf967c 100644 --- a/test-harness/src/lib.rs +++ b/test-harness/src/lib.rs @@ -1,4 +1,4 @@ -//! Test harness library for `ghcid-ng` integration tests. +//! Test harness library for `ghciwatch` integration tests. #![deny(missing_docs)] #![deny(rustdoc::broken_intra_doc_links)] @@ -15,13 +15,13 @@ pub mod fs; pub mod internal; -/// Marks a function as an `async` test for use with a [`GhcidNg`] session. +/// Marks a function as an `async` test for use with a [`GhciWatch`] session. /// pub use test_harness_macro::test; -mod ghcid_ng; -pub use ghcid_ng::GhcidNg; -pub use ghcid_ng::GhcidNgBuilder; +mod ghciwatch; +pub use ghciwatch::GhciWatch; +pub use ghciwatch::GhciWatchBuilder; mod ghc_version; pub use ghc_version::GhcVersion; diff --git a/test-harness/src/matcher.rs b/test-harness/src/matcher.rs index c4813166..456ce0f1 100644 --- a/test-harness/src/matcher.rs +++ b/test-harness/src/matcher.rs @@ -223,7 +223,7 @@ mod tests { level: Level::INFO, message: "ghci started in 2.44s".to_owned(), fields: Default::default(), - target: "ghcid_ng::ghci".to_owned(), + target: "ghciwatch::ghci".to_owned(), span: Some(Span { name: "ghci".to_owned(), rest: Default::default(), @@ -246,14 +246,14 @@ mod tests { #[test] fn test_matcher_spans_and_target() { let matcher = Matcher::span_close() - .in_module("ghcid_ng::ghci") + .in_module("ghciwatch::ghci") .in_spans(["on_action", "reload"]); let event = Event { timestamp: "2023-08-25T22:14:30.993920Z".to_owned(), level: Level::DEBUG, message: "close".to_owned(), fields: Default::default(), - target: "ghcid_ng::ghci".to_owned(), + target: "ghciwatch::ghci".to_owned(), span: Some(Span::new("reload")), spans: vec![Span::new("on_action"), Span::new("reload")], }; @@ -294,13 +294,13 @@ mod tests { // Different target (nested). assert!(!matcher.matches(&Event { - target: "ghcid_ng::ghci::stderr".to_owned(), + target: "ghciwatch::ghci::stderr".to_owned(), ..event.clone() })); // Different target (parent). assert!(!matcher.matches(&Event { - target: "ghcid_ng".to_owned(), + target: "ghciwatch".to_owned(), ..event.clone() })); } @@ -313,7 +313,7 @@ mod tests { level: Level::INFO, message: "ghci started in 2.44s".to_owned(), fields: Default::default(), - target: "ghcid_ng::ghci".to_owned(), + target: "ghciwatch::ghci".to_owned(), span: Some(Span { name: "ghci".to_owned(), rest: Default::default(), @@ -396,7 +396,7 @@ mod tests { ("time.idle".into(), "246µs".into()), ] .into(), - target: "ghcid_ng::ghci::error_log".into(), + target: "ghciwatch::ghci::error_log".into(), span: Some(Span { name: "error_log_write".into(), rest: [( diff --git a/test-harness/src/tracing_reader.rs b/test-harness/src/tracing_reader.rs index be75f69e..03b41c3d 100644 --- a/test-harness/src/tracing_reader.rs +++ b/test-harness/src/tracing_reader.rs @@ -21,7 +21,7 @@ impl TracingReader { /// Create a new [`TracingReader`]. /// /// This watches for data to be read from the given `path`. When a line is written to `path` - /// (by `ghcid-ng`), the `TracingReader` will deserialize the line from JSON into an [`Event`] + /// (by `ghciwatch`), the `TracingReader` will deserialize the line from JSON into an [`Event`] /// and send it to the given `sender` for another task to receive. pub async fn new(path: impl AsRef) -> miette::Result { let path = path.as_ref(); diff --git a/tests/dot_ghci.rs b/tests/dot_ghci.rs index 726d9989..afbd37a0 100644 --- a/tests/dot_ghci.rs +++ b/tests/dot_ghci.rs @@ -1,13 +1,13 @@ use test_harness::fs; use test_harness::test; -use test_harness::GhcidNgBuilder; +use test_harness::GhciWatchBuilder; use indoc::indoc; -/// Test that `ghcid-ng` can run with a custom prompt in `.ghci`. +/// Test that `ghciwatch` can run with a custom prompt in `.ghci`. #[test] async fn can_run_with_custom_ghci_prompt() { - let mut session = GhcidNgBuilder::new("tests/data/simple") + let mut session = GhciWatchBuilder::new("tests/data/simple") .before_start(|project| async move { fs::write( project.join(".ghci"), @@ -23,7 +23,7 @@ async fn can_run_with_custom_ghci_prompt() { }) .start() .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); session.wait_until_ready().await.unwrap(); } diff --git a/tests/error_log.rs b/tests/error_log.rs index 4cfa89ae..29fee9fa 100644 --- a/tests/error_log.rs +++ b/tests/error_log.rs @@ -4,48 +4,48 @@ use indoc::indoc; use test_harness::fs; use test_harness::test; use test_harness::GhcVersion::*; -use test_harness::GhcidNgBuilder; +use test_harness::GhciWatchBuilder; use test_harness::Matcher; -/// Test that `ghcid-ng --errors ...` can write the error log. +/// Test that `ghciwatch --errors ...` can write the error log. #[test] async fn can_write_error_log() { let error_path = "ghcid.txt"; - let mut session = GhcidNgBuilder::new("tests/data/simple") + let mut session = GhciWatchBuilder::new("tests/data/simple") .with_args(["--errors", error_path]) .start() .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); let error_path = session.path(error_path); session .wait_until_ready() .await - .expect("ghcid-ng loads ghci"); + .expect("ghciwatch loads ghci"); let error_contents = fs::read(&error_path) .await - .expect("ghcid-ng writes ghcid.txt"); + .expect("ghciwatch writes ghcid.txt"); expect![[r#" All good (4 modules) "#]] .assert_eq(&error_contents); } -/// Test that `ghcid-ng --errors ...` can write compilation errors. +/// Test that `ghciwatch --errors ...` can write compilation errors. /// Then, test that it can reload when modules are changed and will correctly rewrite the error log /// once it's fixed. #[test] async fn can_write_error_log_compilation_errors() { let error_path = "ghcid.txt"; - let mut session = GhcidNgBuilder::new("tests/data/simple") + let mut session = GhciWatchBuilder::new("tests/data/simple") .with_args(["--errors", error_path]) .start() .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); let error_path = session.path(error_path); session .wait_until_ready() .await - .expect("ghcid-ng loads ghci"); + .expect("ghciwatch loads ghci"); let new_module = session.path("src/My/Module.hs"); @@ -63,16 +63,16 @@ async fn can_write_error_log_compilation_errors() { session .wait_until_add() .await - .expect("ghcid-ng loads new modules"); + .expect("ghciwatch loads new modules"); session .assert_logged(Matcher::span_close().in_span("error_log_write")) .await - .expect("ghcid-ng writes ghcid.txt"); + .expect("ghciwatch writes ghcid.txt"); let error_contents = fs::read(&error_path) .await - .expect("ghcid-ng writes ghcid.txt"); + .expect("ghciwatch writes ghcid.txt"); let expected = match session.ghc_version() { Ghc90 | Ghc92 | Ghc94 => expect![[r#" @@ -108,16 +108,16 @@ async fn can_write_error_log_compilation_errors() { session .wait_until_add() .await - .expect("ghcid-ng reloads on changes"); + .expect("ghciwatch reloads on changes"); session .assert_logged(Matcher::span_close().in_span("error_log_write")) .await - .expect("ghcid-ng writes ghcid.txt"); + .expect("ghciwatch writes ghcid.txt"); let error_contents = fs::read(&error_path) .await - .expect("ghcid-ng writes ghcid.txt"); + .expect("ghciwatch writes ghcid.txt"); expect![[r#" All good (5 modules) diff --git a/tests/eval.rs b/tests/eval.rs index e01c5cfc..bc65a0ce 100644 --- a/tests/eval.rs +++ b/tests/eval.rs @@ -2,67 +2,70 @@ use indoc::indoc; use test_harness::fs; use test_harness::test; -use test_harness::GhcidNgBuilder; +use test_harness::GhciWatchBuilder; use test_harness::Matcher; -/// Test that `ghcid-ng` can eval commands and invalidate its cache of eval commands. +/// Test that `ghciwatch` can eval commands and invalidate its cache of eval commands. #[test] async fn can_eval_commands() { let module_path = "src/MyModule.hs"; let cmd = "-- $> example ++ example"; - let mut session = GhcidNgBuilder::new("tests/data/simple") + let mut session = GhciWatchBuilder::new("tests/data/simple") .with_arg("--enable-eval") .before_start(move |path| async move { fs::append(path.join(module_path), format!("\n{cmd}\n")).await }) .start() .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); let module_path = session.path(module_path); session .wait_until_started() .await - .expect("ghcid-ng didn't start in time"); + .expect("ghciwatch didn't start in time"); let eval_message = Matcher::message(r"MyModule.hs:\d+:\d+: example \+\+ example"); session .assert_logged(&eval_message) .await - .expect("ghcid-ng evals commands"); + .expect("ghciwatch evals commands"); session .assert_logged(Matcher::message("Read line").with_field("line", "exampleexample")) .await - .expect("ghcid-ng evals commands"); + .expect("ghciwatch evals commands"); // Erase the command. fs::replace(module_path, cmd, "").await.unwrap(); - session.wait_until_reload().await.expect("ghcid-ng reloads"); + session + .wait_until_reload() + .await + .expect("ghciwatch reloads"); session .assert_not_logged( &eval_message, Matcher::span_close() .in_span("reload") - .in_module("ghcid_ng::ghci"), + .in_module("ghciwatch::ghci"), ) .await .unwrap(); } -/// Test that `ghcid-ng` can read eval commands in changed files. -/// Also test that `ghcid-ng` can parse multiline eval commands. +/// Test that `ghciwatch` can read eval commands in changed files. +/// Also test that `ghciwatch` can parse multiline eval commands. #[test] async fn can_load_new_eval_commands_multiline() { - let mut session = GhcidNgBuilder::new("tests/data/simple") + let mut session = GhciWatchBuilder::new("tests/data/simple") .with_arg("--enable-eval") .start() .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); session .wait_until_ready() .await - .expect("ghcid-ng didn't start in time"); + .expect("ghciwatch didn't start in time"); let module_path = session.path("src/MyModule.hs"); let cmd = indoc!( @@ -80,24 +83,27 @@ async fn can_load_new_eval_commands_multiline() { session .assert_logged(&eval_message) .await - .expect("ghcid-ng evals commands"); + .expect("ghciwatch evals commands"); session .assert_logged( Matcher::message("Read line").with_field("line", r#"^"exampleexampleexample"$"#), ) .await - .expect("ghcid-ng evals commands"); + .expect("ghciwatch evals commands"); // Erase the command. fs::replace(module_path, eval_cmd, "").await.unwrap(); - session.wait_until_reload().await.expect("ghcid-ng reloads"); + session + .wait_until_reload() + .await + .expect("ghciwatch reloads"); session .assert_not_logged( &eval_message, Matcher::span_close() .in_span("reload") - .in_module("ghcid_ng::ghci"), + .in_module("ghciwatch::ghci"), ) .await .unwrap(); diff --git a/tests/failed_modules.rs b/tests/failed_modules.rs index 9812e428..f904de04 100644 --- a/tests/failed_modules.rs +++ b/tests/failed_modules.rs @@ -1,28 +1,28 @@ use test_harness::fs; use test_harness::test; -use test_harness::GhcidNgBuilder; +use test_harness::GhciWatchBuilder; -/// Test that `ghcid-ng` can start with compile errors. +/// Test that `ghciwatch` can start with compile errors. /// -/// This is a regression test for [#43](https://github.com/MercuryTechnologies/ghcid-ng/issues/43). +/// This is a regression test for [#43](https://github.com/MercuryTechnologies/ghciwatch/issues/43). #[test] async fn can_start_with_failed_modules() { let module_path = "src/MyModule.hs"; - let mut session = GhcidNgBuilder::new("tests/data/simple") + let mut session = GhciWatchBuilder::new("tests/data/simple") .before_start(move |path| async move { fs::replace(path.join(module_path), "example :: String", "example :: ()").await }) .start() .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); let module_path = session.path(module_path); session .assert_logged("Compilation failed") .await - .expect("ghcid-ng fails to load with errors"); + .expect("ghciwatch fails to load with errors"); - session.wait_until_ready().await.expect("ghcid-ng loads"); + session.wait_until_ready().await.expect("ghciwatch loads"); fs::replace(&module_path, "example :: ()", "example :: String") .await @@ -31,5 +31,5 @@ async fn can_start_with_failed_modules() { session .assert_logged("Compilation succeeded") .await - .expect("ghcid-ng reloads fixed modules"); + .expect("ghciwatch reloads fixed modules"); } diff --git a/tests/hooks.rs b/tests/hooks.rs index f2b82a14..179f7843 100644 --- a/tests/hooks.rs +++ b/tests/hooks.rs @@ -1,16 +1,16 @@ use test_harness::fs; use test_harness::test; -use test_harness::GhcidNgBuilder; +use test_harness::GhciWatchBuilder; use test_harness::Matcher; -/// Test that `ghcid-ng` can run its lifecycle hooks. +/// Test that `ghciwatch` can run its lifecycle hooks. /// /// The strategy here is to set a bunch of hooks that print simple messages. We use multiple hooks /// just to test that it's allowed. Then we trigger the events that make the hooks run and confirm /// that the hooks run. #[test] async fn can_run_hooks() { - let mut session = GhcidNgBuilder::new("tests/data/simple") + let mut session = GhciWatchBuilder::new("tests/data/simple") .with_args([ "--after-startup-ghci", "putStrLn \"after-startup-1\"", @@ -35,7 +35,7 @@ async fn can_run_hooks() { ]) .start() .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); session .assert_logged( diff --git a/tests/load.rs b/tests/load.rs index bac02224..19d9579e 100644 --- a/tests/load.rs +++ b/tests/load.rs @@ -2,30 +2,30 @@ use indoc::indoc; use test_harness::fs; use test_harness::test; -use test_harness::GhcidNg; +use test_harness::GhciWatch; -/// Test that `ghcid-ng` can start up `ghci` and load a session. +/// Test that `ghciwatch` can start up `ghci` and load a session. #[test] async fn can_load() { - let mut session = GhcidNg::new("tests/data/simple") + let mut session = GhciWatch::new("tests/data/simple") .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); session .wait_until_ready() .await - .expect("ghcid-ng loads ghci"); + .expect("ghciwatch loads ghci"); } -/// Test that `ghcid-ng` can load new modules. +/// Test that `ghciwatch` can load new modules. #[test] async fn can_load_new_module() { - let mut session = GhcidNg::new("tests/data/simple") + let mut session = GhciWatch::new("tests/data/simple") .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); session .wait_until_ready() .await - .expect("ghcid-ng loads ghci"); + .expect("ghciwatch loads ghci"); fs::write( session.path("src/My/Module.hs"), indoc!( @@ -40,5 +40,5 @@ async fn can_load_new_module() { session .wait_until_add() .await - .expect("ghcid-ng loads new modules"); + .expect("ghciwatch loads new modules"); } diff --git a/tests/reload.rs b/tests/reload.rs index 0aab375a..a2bd34fa 100644 --- a/tests/reload.rs +++ b/tests/reload.rs @@ -2,19 +2,19 @@ use indoc::indoc; use test_harness::fs; use test_harness::test; -use test_harness::GhcidNg; +use test_harness::GhciWatch; use test_harness::Matcher; -/// Test that `ghcid-ng` can start up and then reload on changes. +/// Test that `ghciwatch` can start up and then reload on changes. #[test] async fn can_reload() { - let mut session = GhcidNg::new("tests/data/simple") + let mut session = GhciWatch::new("tests/data/simple") .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); session .wait_until_ready() .await - .expect("ghcid-ng loads ghci"); + .expect("ghciwatch loads ghci"); fs::append( session.path("src/MyLib.hs"), indoc!( @@ -30,27 +30,27 @@ async fn can_reload() { session .wait_until_reload() .await - .expect("ghcid-ng reloads on changes"); + .expect("ghciwatch reloads on changes"); session .assert_logged( Matcher::span_close() - .in_module("ghcid_ng::ghci") + .in_module("ghciwatch::ghci") .in_spans(["on_action", "reload"]), ) .await - .expect("ghcid-ng finishes reloading"); + .expect("ghciwatch finishes reloading"); } -/// Test that `ghcid-ng` can reload a module that fails to compile. +/// Test that `ghciwatch` can reload a module that fails to compile. #[test] async fn can_reload_after_error() { - let mut session = GhcidNg::new("tests/data/simple") + let mut session = GhciWatch::new("tests/data/simple") .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); session .wait_until_ready() .await - .expect("ghcid-ng loads ghci"); + .expect("ghciwatch loads ghci"); let new_module = session.path("src/My/Module.hs"); fs::write( @@ -67,7 +67,7 @@ async fn can_reload_after_error() { session .wait_until_add() .await - .expect("ghcid-ng loads new modules"); + .expect("ghciwatch loads new modules"); session .assert_logged(Matcher::message("Compilation failed").in_spans(["reload", "add_module"])) .await @@ -80,7 +80,7 @@ async fn can_reload_after_error() { session .wait_until_add() .await - .expect("ghcid-ng reloads on changes"); + .expect("ghciwatch reloads on changes"); session .assert_logged(Matcher::message("Compilation succeeded").in_span("reload")) .await diff --git a/tests/rename.rs b/tests/rename.rs index 4be0f464..affca5c4 100644 --- a/tests/rename.rs +++ b/tests/rename.rs @@ -1,19 +1,19 @@ use test_harness::fs; use test_harness::test; -use test_harness::GhcidNg; +use test_harness::GhciWatch; use test_harness::Matcher; -/// Test that `ghcid-ng` can restart correctly when modules are removed and added (i.e., renamed) +/// Test that `ghciwatch` can restart correctly when modules are removed and added (i.e., renamed) /// at the same time. #[test] async fn can_compile_renamed_module() { - let mut session = GhcidNg::new("tests/data/simple") + let mut session = GhciWatch::new("tests/data/simple") .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); session .wait_until_ready() .await - .expect("ghcid-ng loads ghci"); + .expect("ghciwatch loads ghci"); let module_path = session.path("src/MyModule.hs"); let new_module_path = session.path("src/MyCoolModule.hs"); @@ -22,7 +22,7 @@ async fn can_compile_renamed_module() { session .wait_until_restart() .await - .expect("ghcid-ng restarts on module move"); + .expect("ghciwatch restarts on module move"); session .assert_logged(Matcher::message("Compilation failed").in_span("reload")) @@ -36,7 +36,7 @@ async fn can_compile_renamed_module() { session .wait_until_reload() .await - .expect("ghcid-ng reloads on module change"); + .expect("ghciwatch reloads on module change"); session .assert_logged(Matcher::message("Compilation succeeded").in_span("reload")) diff --git a/tests/restart.rs b/tests/restart.rs index c1ea8c57..70ec7b75 100644 --- a/tests/restart.rs +++ b/tests/restart.rs @@ -2,20 +2,20 @@ use indoc::indoc; use test_harness::fs; use test_harness::test; -use test_harness::GhcidNg; -use test_harness::GhcidNgBuilder; +use test_harness::GhciWatch; +use test_harness::GhciWatchBuilder; use test_harness::Matcher; -/// Test that `ghcid-ng` can restart `ghci` after a module is moved. +/// Test that `ghciwatch` can restart `ghci` after a module is moved. #[test] async fn can_restart_after_module_move() { - let mut session = GhcidNg::new("tests/data/simple") + let mut session = GhciWatch::new("tests/data/simple") .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); session .wait_until_ready() .await - .expect("ghcid-ng loads ghci"); + .expect("ghciwatch loads ghci"); let module_path = session.path("src/My/Module.hs"); fs::write( @@ -32,7 +32,7 @@ async fn can_restart_after_module_move() { session .wait_until_add() .await - .expect("ghcid-ng loads new modules"); + .expect("ghciwatch loads new modules"); { // Rename the module and fix the module name to match the new path. @@ -49,7 +49,7 @@ async fn can_restart_after_module_move() { session .wait_until_restart() .await - .expect("ghcid-ng restarts ghci"); + .expect("ghciwatch restarts ghci"); session .assert_logged( @@ -66,24 +66,24 @@ async fn can_restart_after_module_move() { .unwrap(); } -/// Test that `ghcid-ng` can restart after a custom `--watch-restart` path changes. +/// Test that `ghciwatch` can restart after a custom `--watch-restart` path changes. #[test] async fn can_restart_on_custom_file_change() { - let mut session = GhcidNgBuilder::new("tests/data/simple") + let mut session = GhciWatchBuilder::new("tests/data/simple") .with_args(["--watch-restart", "package.yaml"]) .start() .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); session .wait_until_ready() .await - .expect("ghcid-ng loads ghci"); + .expect("ghciwatch loads ghci"); fs::touch(session.path("package.yaml")).await.unwrap(); session .wait_until_restart() .await - .expect("ghcid-ng restarts when package.yaml changes"); + .expect("ghciwatch restarts when package.yaml changes"); } diff --git a/tests/test.rs b/tests/test.rs index 0fbbde8a..2befc8f5 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,23 +1,23 @@ use expect_test::expect; use test_harness::fs; use test_harness::test; -use test_harness::GhcidNgBuilder; +use test_harness::GhciWatchBuilder; use test_harness::Matcher; -/// Test that `ghcid-ng --test ...` can run a test suite. +/// Test that `ghciwatch --test ...` can run a test suite. #[test] async fn can_run_test_suite_on_reload() { let error_path = "ghcid.txt"; - let mut session = GhcidNgBuilder::new("tests/data/simple") + let mut session = GhciWatchBuilder::new("tests/data/simple") .with_args(["--test-ghci", "TestMain.testMain", "--errors", error_path]) .start() .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); let error_path = session.path(error_path); session .wait_until_ready() .await - .expect("ghcid-ng loads ghci"); + .expect("ghciwatch loads ghci"); fs::touch(session.path("src/MyLib.hs")) .await @@ -26,15 +26,15 @@ async fn can_run_test_suite_on_reload() { session .assert_logged(Matcher::span_close().in_span("error_log_write")) .await - .expect("ghcid-ng writes ghcid.txt"); + .expect("ghciwatch writes ghcid.txt"); session .assert_logged("Finished running tests") .await - .expect("ghcid-ng runs the test suite"); + .expect("ghciwatch runs the test suite"); let error_contents = fs::read(&error_path) .await - .expect("ghcid-ng writes ghcid.txt"); + .expect("ghciwatch writes ghcid.txt"); expect![[r#" All good (4 modules) "#]] diff --git a/tests/watch_extension.rs b/tests/watch_extension.rs index 0c18e5f3..e31ec0d9 100644 --- a/tests/watch_extension.rs +++ b/tests/watch_extension.rs @@ -1,19 +1,19 @@ use test_harness::fs; use test_harness::test; -use test_harness::GhcidNgBuilder; +use test_harness::GhciWatchBuilder; -/// Test that `ghcid-ng` can reload when a file with a `--watch-extension` is changed. +/// Test that `ghciwatch` can reload when a file with a `--watch-extension` is changed. #[test] async fn can_reload_extra_extension() { - let mut session = GhcidNgBuilder::new("tests/data/simple") + let mut session = GhciWatchBuilder::new("tests/data/simple") .with_args(["--watch-extension", "persistentmodels"]) .start() .await - .expect("ghcid-ng starts"); + .expect("ghciwatch starts"); session .wait_until_ready() .await - .expect("ghcid-ng loads ghci"); + .expect("ghciwatch loads ghci"); fs::touch(session.path("src/my_model.persistentmodels")) .await @@ -22,5 +22,5 @@ async fn can_reload_extra_extension() { session .wait_until_reload() .await - .expect("ghcid-ng reloads when a `.persistentmodels` file is created"); + .expect("ghciwatch reloads when a `.persistentmodels` file is created"); }