summaryrefslogtreecommitdiffstats
path: root/src/shell_install/nushell.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/shell_install/nushell.rs')
-rw-r--r--src/shell_install/nushell.rs123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/shell_install/nushell.rs b/src/shell_install/nushell.rs
new file mode 100644
index 0000000..228a28f
--- /dev/null
+++ b/src/shell_install/nushell.rs
@@ -0,0 +1,123 @@
+//! The goal of this mod is to ensure the launcher shell function
+//! is available for nushell i.e. the `br` shell function can
+//! be used to launch broot (and thus make it possible to execute
+//! some commands, like `cd`, from the starting shell.
+//!
+//! In a correct installation, we have:
+//! - a function declaration script in ~/.local/share/broot/launcher/nushell/br/1
+//! - a link to that script in ~/.config/broot/launcher/nushell/br/1
+//! - a line to source the link in ~/.config/nushell/config.nu
+//! (exact paths depend on XDG variables)
+//!
+//! More info at
+//! https://github.com/Canop/broot/issues/375
+
+use {
+ super::{util, ShellInstall},
+ crate::{
+ conf,
+ errors::*,
+ },
+ directories::BaseDirs,
+ std::path::PathBuf,
+ termimad::{
+ mad_print_inline,
+ },
+};
+
+const NAME: &str = "nushell";
+const VERSION: &str = "1";
+
+const NU_FUNC: &str = r#"
+# This script was automatically generated by the broot program
+# More information can be found in https://github.com/Canop/broot
+# This function starts broot and executes the command
+# it produces, if any.
+# It's needed because some shell commands, like `cd`,
+# have no useful effect if executed in a subshell.
+def _br_cmd [] {
+ let cmd_file = ([ $nu.temp-path, $"broot-(random chars).tmp" ] | path join)
+ touch $cmd_file
+ ^broot --outcmd $cmd_file
+ let target_dir = (open $cmd_file | to text | str replace "^cd\\s+" "" | str trim)
+ rm -p -f $cmd_file
+
+ $target_dir
+}
+alias br = cd (_br_cmd)
+"#;
+
+pub fn get_script() -> &'static str {
+ NU_FUNC
+}
+
+/// return the path to the link to the function script
+fn get_link_path() -> PathBuf {
+ conf::dir().join("launcher").join(NAME).join("br")
+}
+
+/// return the root of
+fn get_nushell_dir() -> Option<PathBuf> {
+ BaseDirs::new()
+ .map(|base_dirs| base_dirs.config_dir().join("nushell"))
+ .filter(|dir| dir.exists())
+}
+
+/// return the path to the script containing the function.
+///
+/// In XDG_DATA_HOME (typically ~/.local/share on linux)
+fn get_script_path() -> PathBuf {
+ conf::app_dirs()
+ .data_dir()
+ .join("launcher")
+ .join(NAME)
+ .join(VERSION)
+}
+
+/// Check for nushell.
+///
+/// Check whether the shell function is installed, install
+/// it if it wasn't refused before or if broot is launched
+/// with --install.
+pub fn install(si: &mut ShellInstall) -> Result<(), ShellInstallError> {
+ debug!("install {NAME}");
+ let Some(nushell_dir) = get_nushell_dir() else {
+ debug!("no nushell config directory. Assuming nushell isn't used.");
+ return Ok(());
+ };
+ info!("nushell seems to be installed");
+ let script_path = get_script_path();
+ si.write_script(&script_path, NU_FUNC)?;
+ let link_path = get_link_path();
+ si.create_link(&link_path, &script_path)?;
+
+ let escaped_path = link_path.to_string_lossy().replace(' ', "\\ ");
+ let source_line = format!("source {}", &escaped_path);
+
+ let sourcing_path = nushell_dir.join("config.nu");
+ if !sourcing_path.exists() {
+ warn!("Unexpected lack of config.nu file");
+ return Ok(());
+ }
+ if sourcing_path.is_dir() {
+ warn!("config.nu file");
+ return Ok(());
+ }
+ let sourcing_path_str = sourcing_path.to_string_lossy();
+ if util::file_contains_line(&sourcing_path, &source_line)? {
+ mad_print_inline!(
+ &si.skin,
+ "`$0` already patched, no change made.\n",
+ &sourcing_path_str,
+ );
+ } else {
+ util::append_to_file(&sourcing_path, format!("\n{source_line}\n"))?;
+ mad_print_inline!(
+ &si.skin,
+ "`$0` successfully patched, you can make the function immediately available with `source $0`\n",
+ &sourcing_path_str,
+ );
+ }
+ si.done = true;
+ Ok(())
+}