Repository: FuelLabs/fuelup (rust)

Issue:
fuelup default <name>
### Problem you are trying to solve

When choosing a name that does not exist either prompt the user to use the `fuelup show` command to check the toolchains or preferably automatically show the installed toolchains below.

![image](https://github.com/FuelLabs/fuelup/assets/36463/1e523140-acf5-42bc-b4c6-25d32011d245)
![image](https://github.com/FuelLabs/fuelup/assets/36463/509fc682-c5f1-4114-9974-5ff136953fa7)
Capitalize the `d` in `default`

![image](https://github.com/FuelLabs/fuelup/assets/36463/d1764bf2-3785-4616-9c90-521bd206f8ad)


### Solution you'd like

When choosing a name that does not exist either prompt the user to use the `fuelup show` command to check the toolchains or preferably automatically show the installed toolchains below.

### Notes

_No response_

Pull request:
Show installed toolchains if a user tries to set an incorrect toolchain name to the default.
closes #557

Patch:
diff --git a/src/ops/fuelup_default.rs b/src/ops/fuelup_default.rs
index abccdd12..c2d1850a 100644
--- a/src/ops/fuelup_default.rs
+++ b/src/ops/fuelup_default.rs
@@ -3,6 +3,8 @@ use std::str::FromStr;
 use tracing::info;
 
 use crate::{
+    config,
+    fmt::print_header,
     path::settings_file,
     settings::SettingsFile,
     toolchain::{DistToolchainDescription, Toolchain},
@@ -43,7 +45,17 @@ pub fn default(toolchain: Option<String>) -> Result<()> {
     };
 
     if !new_default.exists() {
-        bail!("Toolchain with name '{}' does not exist", &new_default.name);
+        let cfg = config::Config::from_env()?;
+        let toolchains = cfg.list_toolchains()?;
+
+        info!("Toolchain with name '{}' does not exist", &new_default.name);
+        print_header("Installed toolchains");
+        for toolchain in toolchains {
+            info!("{}", toolchain);
+        }
+        // TODO: we should consider migrating to use thiserror in order to return a custom error here
+        // so we can match on it and prompt the user for another attempt.
+        bail!("");
     };
 
     let settings = SettingsFile::new(settings_file());
@@ -51,7 +63,7 @@ pub fn default(toolchain: Option<String>) -> Result<()> {
         s.default_toolchain = Some(new_default.name.clone());
         Ok(())
     })?;
-    info!("default toolchain set to '{}'", new_default.name);
+    info!("Default toolchain set to '{}'", new_default.name);
 
     Ok(())
 }
diff --git a/src/ops/fuelup_show.rs b/src/ops/fuelup_show.rs
index 08741b68..7822b26f 100644
--- a/src/ops/fuelup_show.rs
+++ b/src/ops/fuelup_show.rs
@@ -20,7 +20,7 @@ pub fn show() -> Result<()> {
     info!("{}: {}", bold("Default host"), TargetTriple::from_host()?);
     info!("{}: {}", bold("fuelup home"), fuelup_dir().display());
 
-    print_header("installed toolchains");
+    print_header("Installed toolchains");
     let cfg = Config::from_env()?;
     let mut active_toolchain = Toolchain::from_settings()?;
 
diff --git a/src/ops/fuelup_toolchain/new.rs b/src/ops/fuelup_toolchain/new.rs
index 63e331aa..eda3b89c 100644
--- a/src/ops/fuelup_toolchain/new.rs
+++ b/src/ops/fuelup_toolchain/new.rs
@@ -30,7 +30,7 @@ pub fn new(command: NewCommand) -> Result<()> {
     ensure_dir_exists(&toolchains_dir.join(toolchain_bin_dir))?;
     info!(
         "New toolchain initialized: {name}
-default toolchain set to '{name}'"
+Default toolchain set to '{name}'"
     );
 
     Ok(())


Test patch:
diff --git a/tests/default.rs b/tests/default.rs
index fb9a7479..109f7086 100644
--- a/tests/default.rs
+++ b/tests/default.rs
@@ -36,14 +36,14 @@ fn fuelup_default_latest_and_custom() -> Result<()> {
     testcfg::setup(FuelupState::LatestAndCustomInstalled, &|cfg| {
         let output = cfg.fuelup(&["default", "latest"]);
         let expected_stdout = format!(
-            "default toolchain set to 'latest-{}'\n",
+            "Default toolchain set to 'latest-{}'\n",
             TargetTriple::from_host().unwrap()
         );
 
         assert_eq!(output.stdout, expected_stdout);
 
         let output = cfg.fuelup(&["default", CUSTOM_TOOLCHAIN_NAME]);
-        let expected_stdout = format!("default toolchain set to '{CUSTOM_TOOLCHAIN_NAME}'\n");
+        let expected_stdout = format!("Default toolchain set to '{CUSTOM_TOOLCHAIN_NAME}'\n");
 
         assert_eq!(output.stdout, expected_stdout);
     })?;
@@ -54,12 +54,15 @@ fn fuelup_default_latest_and_custom() -> Result<()> {
 #[test]
 fn fuelup_default_uninstalled_toolchain() -> Result<()> {
     testcfg::setup(FuelupState::LatestToolchainInstalled, &|cfg| {
+        let triple = TargetTriple::from_host().unwrap();
         let output = cfg.fuelup(&["default", "nightly"]);
         let expected_stdout = format!(
-            "Toolchain with name 'nightly-{}' does not exist\n",
-            TargetTriple::from_host().unwrap()
+            "Toolchain with name 'nightly-{}' does not exist\n\n\
+            \u{1b}[1mInstalled toolchains\u{1b}[0m\n\
+            --------------------\n\
+            latest-{}\n\n",
+            triple, triple
         );
-
         assert_eq!(output.stdout, expected_stdout);
     })?;
 
@@ -71,7 +74,7 @@ fn fuelup_default_nightly() -> Result<()> {
     testcfg::setup(FuelupState::AllInstalled, &|cfg| {
         let output = cfg.fuelup(&["default", "nightly"]);
         let expected_stdout = format!(
-            "default toolchain set to 'nightly-{}'\n",
+            "Default toolchain set to 'nightly-{}'\n",
             TargetTriple::from_host().unwrap()
         );
 
@@ -88,7 +91,7 @@ fn fuelup_default_nightly_and_nightly_date() -> Result<()> {
         let stdout = String::from_utf8_lossy(&stripped);
 
         let expected_stdout = format!(
-            "default toolchain set to 'nightly-{}'\n",
+            "Default toolchain set to 'nightly-{}'\n",
             TargetTriple::from_host().unwrap()
         );
         assert_eq!(stdout, expected_stdout);
@@ -97,7 +100,7 @@ fn fuelup_default_nightly_and_nightly_date() -> Result<()> {
             strip_ansi_escapes::strip(cfg.fuelup(&["default", &format!("nightly-{DATE}")]).stdout);
         let stdout = String::from_utf8_lossy(&stripped);
         let expected_stdout = format!(
-            "default toolchain set to 'nightly-{}-{}'\n",
+            "Default toolchain set to 'nightly-{}-{}'\n",
             DATE,
             TargetTriple::from_host().unwrap()
         );
@@ -120,3 +123,23 @@ fn fuelup_default_override() -> Result<()> {
 
     Ok(())
 }
+
+#[test]
+fn fuelup_default_missing_toolchain() -> Result<()> {
+    testcfg::setup(FuelupState::AllInstalled, &|cfg| {
+        let triple = TargetTriple::from_host().unwrap();
+        let output = cfg.fuelup(&["default", "abcd"]);
+        let expected_stdout = format!(
+            "Toolchain with name 'abcd' does not exist\n\n\
+            \u{1b}[1mInstalled toolchains\u{1b}[0m\n\
+            --------------------\n\
+            latest-{triple}\n\
+            nightly-{triple}\n\
+            nightly-2022-08-30-{triple}\n\n"
+        );
+
+        println!("\n{}", output.stdout);
+        assert_eq!(output.stdout, expected_stdout);
+    })?;
+    Ok(())
+}
diff --git a/tests/show.rs b/tests/show.rs
index d39fd352..3f409e8c 100644
--- a/tests/show.rs
+++ b/tests/show.rs
@@ -22,7 +22,7 @@ fn fuelup_show_latest() -> Result<()> {
             r#"Default host: {target}
 fuelup home: {fuelup_home_str}
 
-installed toolchains
+Installed toolchains
 --------------------
 latest-{target} (default)
 nightly-{target}
@@ -66,7 +66,7 @@ fn fuelup_show_and_switch() -> Result<()> {
             r#"Default host: {target}
 fuelup home: {fuelup_home_str}
 
-installed toolchains
+Installed toolchains
 --------------------
 latest-{target} (default)
 nightly-{target}
@@ -102,7 +102,7 @@ latest-{target} (default)
             r#"Default host: {target}
 fuelup home: {fuelup_home_str}
 
-installed toolchains
+Installed toolchains
 --------------------
 latest-{target}
 nightly-{target} (default)
@@ -146,7 +146,7 @@ fn fuelup_show_custom() -> Result<()> {
             r#"Default host: {target}
 fuelup home: {fuelup_home_str}
 
-installed toolchains
+Installed toolchains
 --------------------
 my_toolchain (default)
 
@@ -187,7 +187,7 @@ fn fuelup_show_override() -> Result<()> {
             r#"Default host: {target}
 fuelup home: {fuelup_home_str}
 
-installed toolchains
+Installed toolchains
 --------------------
 latest-{target} (default)
 
@@ -229,7 +229,7 @@ fn fuelup_show_latest_then_override() -> Result<()> {
             r#"Default host: {target}
 fuelup home: {fuelup_home_str}
 
-installed toolchains
+Installed toolchains
 --------------------
 latest-{target} (default)
 nightly-{target}
@@ -278,7 +278,7 @@ latest-{target} (default)
             r#"Default host: {target}
 fuelup home: {fuelup_home_str}
 
-installed toolchains
+Installed toolchains
 --------------------
 latest-{target} (default)
 nightly-{target}
diff --git a/tests/toolchain.rs b/tests/toolchain.rs
index 77bf201b..0c874c4e 100644
--- a/tests/toolchain.rs
+++ b/tests/toolchain.rs
@@ -152,7 +152,7 @@ fn fuelup_toolchain_new() -> Result<()> {
         let output = cfg.fuelup(&["toolchain", "new", CUSTOM_TOOLCHAIN_NAME]);
         let expected_stdout = format!(
             "New toolchain initialized: {CUSTOM_TOOLCHAIN_NAME}
-default toolchain set to '{CUSTOM_TOOLCHAIN_NAME}'\n"
+Default toolchain set to '{CUSTOM_TOOLCHAIN_NAME}'\n"
         );
 
         assert_eq!(output.stdout, expected_stdout);