Explorar o código

优化special_keycode结构 (#4)

将special_keycode模块重写为枚举类型,根据社区模板修改makefile文件,优化字符读取相关代码结构
MemoryShore hai 5 meses
pai
achega
81c6126119
Modificáronse 7 ficheiros con 210 adicións e 144 borrados
  1. 2 0
      .cargo/config.toml
  2. 2 1
      .gitignore
  3. 6 10
      Cargo.toml
  4. 31 18
      Makefile
  5. 33 14
      src/main.rs
  6. 2 2
      src/shell/command/mod.rs
  7. 134 99
      src/shell/mod.rs

+ 2 - 0
.cargo/config.toml

@@ -0,0 +1,2 @@
+[build]
+target = "x86_64-unknown-linux-musl"

+ 2 - 1
.gitignore

@@ -1,2 +1,3 @@
 /target
-/Cargo.lock
+Cargo.lock
+/install/

+ 6 - 10
Cargo.toml

@@ -2,21 +2,17 @@
 name = "NovaShell"
 version = "0.1.0"
 edition = "2021"
+description = "Shell of DragonOS"
+authors = [ "MemoryShore <1353318529@qq.com>" ]
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
-[[bin]]
-name = "NovaShell"
-path = "src/main.rs"
-
 [dependencies]
 dragonos-dsc = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/dragonos-dsc.git", rev = "7c654bcccc" }
 lazy_static = "1.4.0"
 regex = "1.10.2"
 libc = "0.2"
-
-[profile.release]
-panic = 'abort'
-
-[profile.dev]
-panic = 'abort'
+num-traits = "0.2"
+num-derive = "0.4"
+num_enum = "0.5.1"
+num_enum_derive = "0.7.1"

+ 31 - 18
Makefile

@@ -1,28 +1,41 @@
-export RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static
-export RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup
+# The toolchain we use.
+# You can get it by running DragonOS' `tools/bootstrap.sh`
+TOOLCHAIN="+nightly-2023-08-15-x86_64-unknown-linux_dragonos-gnu"
+RUSTFLAGS+="-C target-feature=+crt-static -C link-arg=-no-pie"
 
-OUTPUT_DIR = $(DADK_BUILD_CACHE_DIR_NOVA_SHELL_0_1_0)
-TMP_INSTALL_DIR=$(OUTPUT_DIR)/tmp_install
+# 如果是在dadk中编译,那么安装到dadk的安装目录中
+INSTALL_DIR?=$(DADK_CURRENT_BUILD_DIR)
+# 如果是在本地编译,那么安装到当前目录下的install目录中
+INSTALL_DIR?=./install
 
-all: build
+
+run:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run
 
 build:
-	RUSTFLAGS='-C target-feature=+crt-static -C link-arg=-no-pie' cargo build --target=x86_64-unknown-linux-musl --release
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build
 
-install:
-	mkdir -p $(TMP_INSTALL_DIR)
-	mkdir -p $(OUTPUT_DIR)
+clean:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean
 
-	RUSTFLAGS='-C target-feature=+crt-static -C link-arg=-no-pie' cargo install --target=x86_64-unknown-linux-musl --path .  --root $(TMP_INSTALL_DIR)
-	mv $(TMP_INSTALL_DIR)/bin/NovaShell $(OUTPUT_DIR)/NovaShell
-	rm -rf $(TMP_INSTALL_DIR)
+test:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test
 
-clean:
-	cargo clean
+doc:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc
+
+run-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --release
+
+build-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --release
 
+clean-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --release
 
-fmt:
-	cargo fmt
+test-release:
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --release
 
-fmt-check:
-	cargo fmt --check
+.PHONY: install
+install: 
+	RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --path . --no-track --root $(INSTALL_DIR) --force

+ 33 - 14
src/main.rs

@@ -3,6 +3,9 @@ extern crate libc;
 #[macro_use]
 extern crate lazy_static;
 
+#[macro_use]
+extern crate num_derive;
+
 use std::{
     collections::HashMap,
     fs::File,
@@ -12,22 +15,38 @@ use std::{
     vec::Vec,
 };
 
+use num_enum::TryFromPrimitive;
+
 pub const ROOT_PATH: &str = "/";
 
 mod shell;
 
-pub mod special_keycode {
-    pub const LF: u8 = b'\n';
-    pub const CR: u8 = b'\r';
-    pub const DL: u8 = b'\x7f';
-    pub const BS: u8 = b'\x08';
-    pub const SPACE: u8 = b' ';
-    pub const TAB: u8 = b'\t';
-
-    pub const UP: u8 = 72;
-    pub const DOWN: u8 = 80;
-    pub const LEFT: u8 = 75;
-    pub const RIGHT: u8 = 77;
+#[repr(u8)]
+#[derive(Debug, FromPrimitive, TryFromPrimitive, ToPrimitive, PartialEq, Eq, Clone)]
+#[allow(dead_code)]
+pub enum SpecialKeycode {
+    LF = b'\n',
+    CR = b'\r',
+    Delete = b'\x7f',
+    BackSpace = b'\x08',
+    Tab = b'\t',
+
+    FunctionKey = 0xE0,
+    PauseBreak = 0xE1,
+
+    Up = 0x48,
+    Down = 0x50,
+    Left = 0x4B,
+    Right = 0x4D,
+
+    Home = 0x47,
+    End = 0x4F,
+}
+
+impl Into<u8> for SpecialKeycode {
+    fn into(self) -> u8 {
+        self as u8
+    }
 }
 
 struct Env(std::collections::HashMap<String, String>);
@@ -45,7 +64,7 @@ impl Env {
     }
 
     fn read_env() {
-        let env = &mut ENV.lock().unwrap().0;
+        let mut env = ENV.lock().unwrap();
         let mut file = File::open("/etc/profile").unwrap();
         let mut buf: Vec<u8> = Vec::new();
         file.read_to_end(&mut buf).unwrap();
@@ -62,7 +81,7 @@ impl Env {
             })
             .collect::<Vec<(&str, &str)>>()
         {
-            env.insert(String::from(name), String::from(value));
+            env.0.insert(String::from(name), String::from(value));
         }
     }
 

+ 2 - 2
src/shell/command/mod.rs

@@ -14,7 +14,7 @@ use std::{
 
 use crate::shell::Shell;
 use crate::Env;
-use crate::{special_keycode::*, ROOT_PATH};
+use crate::ROOT_PATH;
 
 mod help;
 
@@ -274,7 +274,7 @@ impl Shell {
                 print!("{}    ", entry.file_name().into_string().unwrap());
             }
         }
-        print!("{}", String::from_utf8(vec![CR, LF]).unwrap());
+        println!();
         return Ok(());
     }
 

+ 134 - 99
src/shell/mod.rs

@@ -7,7 +7,7 @@ use std::{
     vec::Vec,
 };
 
-use crate::{special_keycode::*, Env};
+use crate::{Env, SpecialKeycode};
 
 use command::{BuildInCmd, Command};
 
@@ -47,7 +47,7 @@ impl Shell {
             self.history_commands.push(buf);
             Printer::print_prompt(&self.current_dir);
             if self.readline(0) == 0 {
-                Printer::print(&[CR, LF]);
+                println!();
                 break;
             }
             let command_bytes = self.history_commands.last().unwrap().clone();
@@ -93,7 +93,7 @@ impl Shell {
             .unwrap();
         for command_line in &self.executed_commands {
             file.write_all(&command_line[..]).unwrap();
-            file.write_all(&[LF]).unwrap();
+            file.write_all(&[SpecialKeycode::LF.into()]).unwrap();
         }
     }
 
@@ -124,98 +124,62 @@ impl Shell {
             // if stdin.read(&mut key).ok() != Some(1) {
             //     continue;
             // }
-            if key[0] == 224 {
-                Self::read_char(&mut key[0]);
-                // stdin.read(&mut key).unwrap();
-                if key[0] == b'\x1b' {
-                    panic!();
-                }
-                if key[0] == UP || key[0] == DOWN {
-                    if key[0] == UP && command_index > 0 {
-                        command_index -= 1;
-                    }
-                    if key[0] == DOWN && command_index < len {
-                        command_index += 1;
-                    }
-                    let old_length = buf.len();
-                    buf = history_commands.get_mut(command_index).unwrap();
-                    Printer::replace(&buf, old_length);
-                    cursor = buf.len() - 1;
-                }
-
-                if key[0] == LEFT || key[0] == RIGHT {
-                    match key[0] {
-                        LEFT => {
-                            if cursor > 0 {
-                                Printer::set_cursor(buf, cursor, cursor - 1);
-                                cursor -= 1;
+            if let Ok(special_key) = SpecialKeycode::try_from(key[0]) {
+                match special_key {
+                    SpecialKeycode::FunctionKey => {
+                        Self::read_char(&mut key[0]);
+                        let special_key = SpecialKeycode::try_from(key[0]).unwrap();
+                        match special_key {
+                            SpecialKeycode::Up => {
+                                if command_index > 0 {
+                                    command_index -= 1;
+                                }
+                                let old_length = buf.len();
+                                buf = history_commands.get_mut(command_index).unwrap();
+                                Printer::replace(&buf, old_length);
+                                cursor = buf.len() - 1;
                             }
-                        }
 
-                        RIGHT => {
-                            if cursor < buf.len() - 1 {
-                                Printer::set_cursor(buf, cursor, cursor + 1);
-                                cursor += 1;
+                            SpecialKeycode::Down => {
+                                if command_index < len {
+                                    command_index += 1;
+                                }
+                                let old_length = buf.len();
+                                buf = history_commands.get_mut(command_index).unwrap();
+                                Printer::replace(&buf, old_length);
+                                cursor = buf.len() - 1;
                             }
-                        }
 
-                        _ => {}
-                    }
-                }
-            } else {
-                if key[0] == TAB && buf.len() > 1 && buf[cursor - 1] != b' ' {
-                    let command: String = String::from_utf8(buf[..cursor].to_vec()).unwrap();
-                    let mut command_frag = command.split_ascii_whitespace().collect::<Vec<_>>();
-                    let incomplete_frag = command_frag.pop().unwrap();
-                    let mut incomplete_len: usize = incomplete_frag.len();
-                    let candidates = match command_frag.len() {
-                        0 => Printer::complete_command(incomplete_frag),
-                        1.. => {
-                            if let Some(index) = incomplete_frag.rfind('/') {
-                                incomplete_len = incomplete_frag.len() - index - 1;
-                            } else {
-                                incomplete_len = incomplete_frag.len();
+                            SpecialKeycode::Left => {
+                                if cursor > 0 {
+                                    Printer::set_cursor(buf, cursor, cursor - 1);
+                                    cursor -= 1;
+                                }
                             }
-                            Printer::complete_path(incomplete_frag)
-                        }
-                        _ => Vec::new(),
-                    };
-                    match candidates.len() {
-                        1 => {
-                            let complete_part = candidates[0][incomplete_len..].as_bytes();
-
-                            Printer::delete_from_index(cursor, buf.len());
 
-                            // stdout.write_all(complete_part).unwrap();
-                            Printer::print(complete_part);
+                            SpecialKeycode::Right => {
+                                if cursor < buf.len() - 1 {
+                                    Printer::set_cursor(buf, cursor, cursor + 1);
+                                    cursor += 1;
+                                }
+                            }
 
-                            Printer::print_cursor(buf[cursor]);
-                            Printer::print(&buf[cursor + 1..]);
+                            SpecialKeycode::Home => {
+                                Printer::set_cursor(buf, cursor, 0);
+                            }
 
-                            buf.splice(cursor..cursor, complete_part.iter().cloned());
-                            cursor += candidates[0].len() - incomplete_len;
-                        }
-                        2.. => {
-                            Printer::delete_from_index(cursor, buf.len());
-                            Printer::print(&buf[cursor..buf.len()]);
-                            Printer::print(&[CR, LF]);
-                            for candidate in candidates {
-                                print!("{candidate}    ");
+                            SpecialKeycode::End => {
+                                Printer::set_cursor(buf, cursor, buf.len());
                             }
-                            Printer::print(&[CR, LF]);
-                            Printer::print_prompt(&prompt);
-                            Printer::print(&buf[..buf.len() - 1]);
-                            Printer::print_cursor(b' ');
+
+                            _ => {}
                         }
-                        _ => {}
                     }
-                }
 
-                match key[0] {
-                    CR | LF => {
+                    SpecialKeycode::LF | SpecialKeycode::CR => {
                         if cursor > 0 {
                             Printer::set_cursor(buf, cursor, buf.len());
-                            Printer::print(&[CR, LF]);
+                            println!();
                             let mut command = buf.clone();
                             buf = history_commands.get_mut(len).unwrap();
                             buf.clear();
@@ -224,13 +188,78 @@ impl Shell {
                             return 1;
                         }
                     }
-                    BS | DL => {
+
+                    SpecialKeycode::BackSpace => {
                         if cursor > 0 {
-                            Printer::delete(cursor, 1, buf);
+                            Printer::delete_to_cursor(cursor, 1, buf);
                             buf.remove(cursor - 1);
                             cursor -= 1;
                         }
                     }
+
+                    SpecialKeycode::Delete => {
+                        if cursor < buf.len() - 1 {
+                            Printer::delete(cursor, buf);
+                            buf.remove(cursor);
+                        }
+                    }
+
+                    SpecialKeycode::Tab => {
+                        if buf.len() > 1 && buf[cursor - 1] != b' ' {
+                            let command: String =
+                                String::from_utf8(buf[..cursor].to_vec()).unwrap();
+                            let mut command_frag =
+                                command.split_ascii_whitespace().collect::<Vec<_>>();
+                            let incomplete_frag = command_frag.pop().unwrap();
+                            let mut incomplete_len: usize = incomplete_frag.len();
+                            let candidates = match command_frag.len() {
+                                0 => Printer::complete_command(incomplete_frag),
+                                1.. => {
+                                    if let Some(index) = incomplete_frag.rfind('/') {
+                                        incomplete_len = incomplete_frag.len() - index - 1;
+                                    } else {
+                                        incomplete_len = incomplete_frag.len();
+                                    }
+                                    Printer::complete_path(incomplete_frag)
+                                }
+                                _ => Vec::new(),
+                            };
+                            match candidates.len() {
+                                1 => {
+                                    let complete_part = candidates[0][incomplete_len..].as_bytes();
+
+                                    Printer::delete_from_index(cursor, buf.len());
+
+                                    // stdout.write_all(complete_part).unwrap();
+                                    Printer::print(complete_part);
+
+                                    Printer::print_cursor(buf[cursor]);
+                                    Printer::print(&buf[cursor + 1..]);
+
+                                    buf.splice(cursor..cursor, complete_part.iter().cloned());
+                                    cursor += candidates[0].len() - incomplete_len;
+                                }
+                                2.. => {
+                                    Printer::delete_from_index(cursor, buf.len());
+                                    Printer::print(&buf[cursor..buf.len()]);
+                                    println!();
+                                    for candidate in candidates {
+                                        print!("{candidate}    ");
+                                    }
+                                    println!();
+                                    Printer::print_prompt(&prompt);
+                                    Printer::print(&buf[..buf.len() - 1]);
+                                    Printer::print_cursor(b' ');
+                                }
+                                _ => {}
+                            }
+                        }
+                    }
+
+                    _ => todo!(),
+                }
+            } else {
+                match key[0] {
                     1..=31 => {}
                     c => {
                         Printer::insert(cursor, &[c], buf);
@@ -249,17 +278,9 @@ struct Printer;
 impl Printer {
     fn print_prompt(current_dir: &String) {
         io::stdout().flush().unwrap();
-        unsafe {
-            syscall(100000, "[DragonOS]:\0".as_ptr(), 0x0000ff90, 0x00000000);
-
-            syscall(
-                100000,
-                format!("{}\0", current_dir).as_ptr(),
-                0x000088ff,
-                0x00000000,
-            );
-            print!("$ ");
-        }
+        Self::print_color("[DragonOS]:".as_bytes(), 0x0000ff90, 0x00000000);
+        Self::print_color(current_dir.as_bytes(), 0x000088ff, 0x00000000);
+        print!("$ ");
     }
 
     fn print_cursor(c: u8) {
@@ -268,7 +289,11 @@ impl Printer {
 
     fn delete_from_index(index: usize, length: usize) {
         for _i in 0..length - index {
-            Printer::print(&[BS, SPACE, BS]);
+            Printer::print(&[
+                SpecialKeycode::BackSpace.into(),
+                b' ',
+                SpecialKeycode::BackSpace.into(),
+            ]);
         }
     }
 
@@ -279,10 +304,20 @@ impl Printer {
         Printer::print(&buf[cursor + 1..]);
     }
 
-    fn delete(cursor: usize, length: usize, buf: &Vec<u8>) {
-        Printer::delete_from_index(cursor - length, buf.len());
-        Printer::print_cursor(buf[cursor]);
-        Printer::print(&buf[cursor + 1..]);
+    fn delete(cursor: usize, buf: &Vec<u8>) {
+        if cursor < buf.len() - 1 {
+            Printer::delete_from_index(cursor, buf.len());
+            Printer::print_cursor(buf[cursor + 1]);
+            Printer::print(&buf[cursor + 2..]);
+        }
+    }
+
+    fn delete_to_cursor(cursor: usize, length: usize, buf: &Vec<u8>) {
+        if cursor > 0 {
+            Printer::delete_from_index(cursor - length, buf.len());
+            Printer::print_cursor(buf[cursor]);
+            Printer::print(&buf[cursor + 1..]);
+        }
     }
 
     fn replace(bytes: &[u8], old_length: usize) {