cicada 0.9.4

A simple Unix shell.
Documentation
use std::env;
use std::error::Error;
use std::io::Write;
use std::path::{Path, PathBuf};

use crate::parsers;
use crate::shell;
use crate::tools;

use crate::types::Tokens;

pub fn run(sh: &mut shell::Shell, tokens: &Tokens) -> i32 {
    let args = parsers::parser_line::tokens_to_args(&tokens);
    if args.len() > 2 {
        println_stderr!("cicada: cd: too many argument");
        return 1;
    }
    let mut current_dir = PathBuf::new();
    match env::current_dir() {
        Ok(x) => current_dir = x,
        Err(e) => {
            println_stderr!("current_dir() failed: {}", e.description());
        }
    }
    let mut str_current_dir = "";
    match current_dir.to_str() {
        Some(x) => str_current_dir = x,
        None => {
            println_stderr!("current_dir to str failed.");
        }
    }
    let mut dir_to = if args.len() == 1 {
        let home = tools::get_user_home();
        home.to_string()
    } else {
        args[1..].join("")
    };

    if dir_to == "-" {
        if sh.previous_dir == "" {
            println_stderr!("no previous dir");
            return 1;
        }
        dir_to = sh.previous_dir.clone();
    } else if !dir_to.starts_with('/') {
        dir_to = format!("{}/{}", str_current_dir, dir_to);
    }

    if !Path::new(&dir_to).exists() {
        println_stderr!(
            "cicada: cd: {}: No such file or directory",
            args[1..].join("")
        );
        return 1;
    }

    match env::set_current_dir(&dir_to) {
        Ok(_) => {
            if str_current_dir != dir_to {
                sh.previous_dir = str_current_dir.to_string();
            };
            0
        }
        Err(e) => {
            println_stderr!("cicada: cd: {}", e.description());
            1
        }
    }
}