/ firmware / src / programs / shell / path.rs
path.rs
  1  use alloc::string::String as AllocString;
  2  
  3  use crate::services::{identity, system_files};
  4  
  5  pub fn home_dir() -> AllocString {
  6      identity::home_dir()
  7  }
  8  
  9  pub fn ensure_filesystem_hierarchy() {
 10      system_files::initialize_layout();
 11  }
 12  
 13  pub fn display_cwd(cwd: &str) -> AllocString {
 14      let home = home_dir();
 15      if cwd == home {
 16          AllocString::from("~")
 17      } else if cwd.starts_with(home.as_str()) {
 18          let mut display_path = AllocString::from("~");
 19          display_path.push_str(&cwd[home.len()..]);
 20          display_path
 21      } else {
 22          AllocString::from(cwd)
 23      }
 24  }
 25  
 26  pub fn apply_cd(cwd: &mut AllocString, arg: &str) {
 27      let arg = arg.trim();
 28      if arg == "~" || arg.is_empty() {
 29          *cwd = identity::home_dir();
 30          return;
 31      }
 32      if let Some(rest) = arg.strip_prefix("~/") {
 33          *cwd = identity::home_dir();
 34          if !rest.is_empty() {
 35              for part in rest.split('/') {
 36                  match part {
 37                      "" | "." => {}
 38                      ".." => {
 39                          if let Some(position) = cwd.rfind('/') {
 40                              if position == 0 {
 41                                  cwd.truncate(1);
 42                              } else {
 43                                  cwd.truncate(position);
 44                              }
 45                          }
 46                      }
 47                      name => {
 48                          if cwd != "/" {
 49                              cwd.push('/');
 50                          }
 51                          cwd.push_str(name);
 52                      }
 53                  }
 54              }
 55          }
 56          return;
 57      }
 58  
 59      if arg == "/" {
 60          cwd.clear();
 61          cwd.push('/');
 62          return;
 63      }
 64  
 65      if arg.starts_with('/') {
 66          cwd.clear();
 67          cwd.push('/');
 68      }
 69  
 70      for part in arg.split('/') {
 71          match part {
 72              "" | "." => {}
 73              ".." => {
 74                  if let Some(position) = cwd.rfind('/') {
 75                      if position == 0 {
 76                          cwd.truncate(1);
 77                      } else {
 78                          cwd.truncate(position);
 79                      }
 80                  }
 81              }
 82              name => {
 83                  if cwd != "/" {
 84                      cwd.push('/');
 85                  }
 86                  cwd.push_str(name);
 87              }
 88          }
 89      }
 90  }
 91  
 92  pub fn resolve_path(cwd: &str, name: &str) -> AllocString {
 93      if name.starts_with('/') {
 94          AllocString::from(name)
 95      } else {
 96          let mut path = AllocString::from(cwd);
 97          if !path.ends_with('/') {
 98              path.push('/');
 99          }
100          path.push_str(name);
101          path
102      }
103  }