├── .github └── workflows │ └── rust.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── Cross.toml ├── LICENSE ├── README.md ├── renovate.json └── src ├── cmd ├── cat.rs ├── check.rs ├── fs_handle │ ├── can.rs │ ├── cp.rs │ ├── ls.rs │ ├── mkdir.rs │ ├── mod.rs │ ├── rm.rs │ ├── rmdir.rs │ └── touch.rs ├── grep.rs ├── man.rs └── mod.rs ├── lib.rs ├── main.rs └── man ├── README.md ├── cat ├── fs_handle ├── can ├── cp ├── cpdir ├── ls ├── mkdir ├── rm ├── rmdir └── touch ├── grep ├── man └── mod.rs /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ nightly ] 6 | pull_request: 7 | branches: [ nightly ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Build 20 | run: cargo build --verbose 21 | - name: Run tests 22 | run: cargo test --verbose 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | test 3 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "lazy_static" 7 | version = "1.4.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 10 | 11 | [[package]] 12 | name = "libc" 13 | version = "0.2.106" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673" 16 | 17 | [[package]] 18 | name = "memmap2" 19 | version = "0.5.8" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" 22 | dependencies = [ 23 | "libc", 24 | ] 25 | 26 | [[package]] 27 | name = "rustc-hash" 28 | version = "1.1.0" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 31 | 32 | [[package]] 33 | name = "tct" 34 | version = "0.1.0" 35 | dependencies = [ 36 | "lazy_static", 37 | "memmap2", 38 | "rustc-hash", 39 | ] 40 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tct" 3 | version = "0.1.0" 4 | edition = "2018" 5 | license = "MIT" 6 | 7 | [dependencies] 8 | lazy_static = "1.4.0" 9 | memmap2 = "0.5.8" 10 | rustc-hash = "1.1.0" 11 | 12 | [profile.release] 13 | lto = "fat" 14 | codegen-units = 1 15 | -------------------------------------------------------------------------------- /Cross.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tct" 3 | version = "0.1.0" 4 | edition = "2018" 5 | license = "MIT" 6 | 7 | [dependencies] 8 | lazy_static = "1.4.0" 9 | memmap2 = "0.5.0" 10 | rustc-hash = "1.1.0" 11 | 12 | [profile.release] 13 | lto = "fat" 14 | codegen-units = 1 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Tiny Commands Toolchain 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tiny Commands Toolchain: TCT 2 | A 1.62MB (release profile) monolithic commands kit for casual terminal usage without any run-time dependency. MMade in 171 LOC (lines of code). 3 | 4 | ## Usage 5 | For execute a command, just run the `tct` with the first argument being the same **all commands require at least 1 argument**. 6 | 7 | Examples: 8 | | command | launch string | 9 | | :--- | ---: | 10 | | `cat` | `tct cat some_file` | 11 | | `grep` | `tct cat a_string some_file` | 12 | | `mkdir` | `tct mkdir new_dir` | 13 | 14 | ## Benchmarks 15 | Comparision of some tools. Everything with `gnu` prefix means that's from `gnu-coreutils`'s Arch package (version `9.0-2`). 16 | 17 | **Notes**: Some tools as `rg` and `bat` has a **LOT** of features and it's beautiful for user mode. For this reason, some benchmarks will show them as slower than other commands. 18 | 19 | All benchmarks were performed on a 1.89GB RAM 2.6GHz Celeron Dual Core CPU machine~~/potato~~. 20 | 21 | ### `cat` 22 | In a 10KB file: 23 | | Command | Mean [ms] | Min [ms] | Max [ms] | Relative | 24 | |:---|---:|---:|---:|---:| 25 | | `cat lorem.txt` | 1.7 ± 1.4 | 0.0 | 5.2 | 1.00 | 26 | | `./target/release/tct cat lorem.txt` | 2.3 ± 1.7 | 0.0 | 5.9 | 1.33 ± 1.45 | 27 | | `bat lorem.txt` | 97.8 ± 5.9 | 92.6 | 119.5 | 56.09 ± 45.92 | 28 | 29 | In a 10MB file: 30 | | Command | Mean [ms] | Min [ms] | Max [ms] | Relative | 31 | |:---|---:|---:|---:|---:| 32 | | `cat biglorem.txt` | 5.9 ± 2.7 | 1.7 | 12.8 | 2.65 ± 2.36 | 33 | | `./target/release/tct cat biglorem.txt` | 2.2 ± 1.7 | 0.0 | 6.4 | 1.00 | 34 | | `bat biglorem.txt` | 121.7 ± 6.4 | 116.4 | 139.6 | 54.39 ± 41.59 | 35 | 36 | ### `grep` 37 | Searching for all occurrences of `Ipsum` in a 10KB file 38 | | Command | Mean [ms] | Min [ms] | Max [ms] | Relative | 39 | |:---|---:|---:|---:|---:| 40 | | `grep Ipsum lorem.txt` | 5.9 ± 2.8 | 1.5 | 10.9 | 2.56 ± 2.32 | 41 | | `./target/release/tct grep Ipsum lorem.txt` | 2.3 ± 1.8 | 0.0 | 5.9 | 1.00 | 42 | | `rg Ipsum lorem.txt` | 8.5 ± 2.9 | 3.5 | 14.2 | 3.71 ± 3.13 | 43 | 44 | Searching for all occurrences of `Ipsum` in a 10MB file 45 | | Command | Mean [ms] | Min [ms] | Max [ms] | Relative | 46 | |:---|---:|---:|---:|---:| 47 | | `grep Ipsum biglorem.txt` | 5.7 ± 2.9 | 1.7 | 11.6 | 1.00 | 48 | | `./target/release/tct grep Ipsum biglorem.txt` | 36.3 ± 5.7 | 32.3 | 60.4 | 6.33 ± 3.30 | 49 | | `rg Ipsum biglorem.txt` | 24.8 ± 5.1 | 13.8 | 33.1 | 4.33 ± 2.33 | 50 | 51 | ## Compile Tips 52 | Be sure to compile with `release` profile (`cargo build --release`). If you're compiling for local usage, sill can set `RUSTFLAGS` with `-C target-cpu=native` before compile (`RUSTFLAGS='-C target-cpu=native' cargo build --release` on \*NIX, `set RUSTFLAGS='-C target-cpu=native' ; cargo build --release` on Windows) to use your CPU specific instructions for local optimization. 53 | 54 | ## TODO 55 | - [ ] (Add more benchmarks) 56 | - [ ] (Optimize `grep` for large files) 57 | - [ ] (Improve README) 58 | - [ ] (Update manpages) 59 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /src/cmd/cat.rs: -------------------------------------------------------------------------------- 1 | use crate::cmd::ProgResult; 2 | use std::fs::File; 3 | use std::io::{stdout, Write}; 4 | 5 | use memmap2::MmapOptions; 6 | 7 | pub fn cat(paths: &[String]) -> ProgResult { 8 | let out = stdout(); 9 | let mut out = out.lock(); 10 | 11 | paths.iter().skip(1).for_each(|path| { 12 | let buf_reader = unsafe { 13 | MmapOptions::new() 14 | .map(&File::open(path).expect("File not found")) 15 | .expect("Cannot map file") 16 | }; 17 | 18 | out.write_all(&buf_reader[..]) 19 | .expect("Cannot show file content"); 20 | }); 21 | Ok(()) 22 | } 23 | -------------------------------------------------------------------------------- /src/cmd/check.rs: -------------------------------------------------------------------------------- 1 | use crate::cmd::{ProgResult, COMMANDS}; 2 | use std::error::Error; 3 | use std::fmt::Display; 4 | 5 | #[derive(Debug)] 6 | struct CmdCheckError(String); 7 | 8 | impl Display for CmdCheckError { 9 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 10 | write!(f, "{} isn't a valid command", self.0) 11 | } 12 | } 13 | 14 | impl Error for CmdCheckError {} 15 | 16 | pub fn check(cmds: &[String]) -> ProgResult { 17 | for cmd in cmds.iter().skip(1) { 18 | if !COMMANDS.contains_key(cmd.as_str()) { 19 | return Err(Box::new(CmdCheckError(cmd.clone()))); 20 | } 21 | } 22 | Ok(()) 23 | } 24 | -------------------------------------------------------------------------------- /src/cmd/fs_handle/can.rs: -------------------------------------------------------------------------------- 1 | use crate::cmd::ProgResult; 2 | use std::fs; 3 | use std::io::{stdout, Write}; 4 | 5 | pub fn can(paths: &[String]) -> ProgResult { 6 | let out = stdout(); 7 | let mut out = out.lock(); 8 | 9 | paths.iter().skip(1).for_each(|path| { 10 | out.write_all(fs::canonicalize(path).unwrap().to_str().unwrap().as_bytes()) 11 | .expect("Cannot print"); 12 | out.write_all(b"\n").unwrap() 13 | }); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/cmd/fs_handle/cp.rs: -------------------------------------------------------------------------------- 1 | use crate::cmd::ProgResult; 2 | use std::fs::copy; 3 | use std::io::{stdout, Write}; 4 | 5 | pub fn cp(paths: &[String]) -> ProgResult { 6 | let out = stdout(); 7 | let mut out = out.lock(); 8 | let mut iter = paths.iter().skip(1).peekable(); 9 | 10 | while iter.peek().is_some() { 11 | if let Err(error) = copy( 12 | iter.next().unwrap(), 13 | iter.next().expect("Missing target folder"), 14 | ) { 15 | out.write_all(error.to_string().as_bytes()) 16 | .expect("Cannot print"); 17 | } 18 | } 19 | Ok(()) 20 | } 21 | -------------------------------------------------------------------------------- /src/cmd/fs_handle/ls.rs: -------------------------------------------------------------------------------- 1 | use crate::cmd::ProgResult; 2 | use std::fs::{read_dir, DirEntry}; 3 | use std::io::{stdout, StdoutLock, Write}; 4 | 5 | pub fn ls(paths: &[String]) -> ProgResult { 6 | let out = stdout(); 7 | let mut out = out.lock(); 8 | 9 | paths.iter().skip(1).for_each(|path| { 10 | read_dir(path) 11 | .unwrap() 12 | .for_each(|entry| show_file(&mut out, entry.expect("Directory not found"))) 13 | }); 14 | out.write_all(b"\n").expect("Cannot print"); 15 | Ok(()) 16 | } 17 | 18 | #[inline(always)] 19 | pub fn show_file(out: &mut StdoutLock, dir: DirEntry) { 20 | out.write_all(dir.path().file_name().unwrap().to_string_lossy().as_bytes()) 21 | .expect("Cannot print"); 22 | out.write_all(b" ").unwrap(); 23 | } 24 | -------------------------------------------------------------------------------- /src/cmd/fs_handle/mkdir.rs: -------------------------------------------------------------------------------- 1 | use crate::cmd::ProgResult; 2 | use std::fs; 3 | 4 | pub fn mkdir(paths: &[String]) -> ProgResult { 5 | paths 6 | .iter() 7 | .skip(1) 8 | .for_each(|path| fs::create_dir_all(path).unwrap()); 9 | Ok(()) 10 | } 11 | -------------------------------------------------------------------------------- /src/cmd/fs_handle/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod can; 2 | pub mod cp; 3 | pub mod ls; 4 | pub mod mkdir; 5 | pub mod rm; 6 | pub mod rmdir; 7 | pub mod touch; 8 | -------------------------------------------------------------------------------- /src/cmd/fs_handle/rm.rs: -------------------------------------------------------------------------------- 1 | use crate::cmd::ProgResult; 2 | use std::fs; 3 | 4 | pub fn rm(paths: &[String]) -> ProgResult { 5 | paths 6 | .iter() 7 | .skip(1) 8 | .for_each(|path| fs::remove_file(path).unwrap()); 9 | Ok(()) 10 | } 11 | -------------------------------------------------------------------------------- /src/cmd/fs_handle/rmdir.rs: -------------------------------------------------------------------------------- 1 | use crate::cmd::ProgResult; 2 | use std::fs; 3 | 4 | pub fn rmdir(paths: &[String]) -> ProgResult { 5 | paths 6 | .iter() 7 | .skip(1) 8 | .for_each(|path| fs::remove_dir_all(path).unwrap()); 9 | Ok(()) 10 | } 11 | -------------------------------------------------------------------------------- /src/cmd/fs_handle/touch.rs: -------------------------------------------------------------------------------- 1 | use crate::cmd::ProgResult; 2 | use std::fs; 3 | 4 | pub fn touch(paths: &[String]) -> ProgResult { 5 | paths 6 | .iter() 7 | .skip(1) 8 | .for_each(|path| fs::write(path, b"").unwrap()); 9 | Ok(()) 10 | } 11 | -------------------------------------------------------------------------------- /src/cmd/grep.rs: -------------------------------------------------------------------------------- 1 | use crate::cmd::ProgResult; 2 | use std::fs::File; 3 | use std::io::{stdout, StdoutLock, Write}; 4 | 5 | use memmap2::{Mmap, MmapOptions}; 6 | 7 | pub fn grep(items: &[String]) -> ProgResult { 8 | let out = stdout(); 9 | let mut out = out.lock(); 10 | 11 | let pattern = items[1].as_bytes(); 12 | 13 | items.iter().skip(2).for_each(|filepath| { 14 | file_grep(&mut out, pattern, unsafe { 15 | MmapOptions::new() 16 | .map(&File::open(filepath).expect("File not found")) 17 | .expect("Cannot map file") 18 | }) 19 | }); 20 | Ok(()) 21 | } 22 | 23 | pub fn file_grep(out: &mut StdoutLock, pattern: &[u8], buf_reader: Mmap) { 24 | let (mut line_start, mut indx_seq) = (0, 0); 25 | buf_reader.iter().enumerate().for_each(|(i, &b)| { 26 | if indx_seq != pattern.len() { 27 | if b == pattern[indx_seq] { 28 | indx_seq += 1; 29 | } else { 30 | indx_seq = 0; 31 | } 32 | } 33 | 34 | if b == b'\n' { 35 | if indx_seq == pattern.len() { 36 | out.write_all(&buf_reader[line_start..i]) 37 | .expect("Cannot print"); 38 | out.write_all(b"\n").unwrap(); 39 | indx_seq = 0; 40 | } 41 | line_start = i + 1; 42 | } 43 | }); 44 | } 45 | -------------------------------------------------------------------------------- /src/cmd/man.rs: -------------------------------------------------------------------------------- 1 | use crate::cmd::ProgResult; 2 | use crate::man::MANUALS; 3 | use std::io::{stdout, Write}; 4 | 5 | pub fn man(cmds: &[String]) -> ProgResult { 6 | let out = stdout(); 7 | let mut out = out.lock(); 8 | 9 | cmds.iter().skip(1).for_each(|cmd| { 10 | if !MANUALS.contains_key(cmd.as_str()) { 11 | out.write_all(MANUALS[cmd.as_str()].as_bytes()) 12 | .expect("Cannot show manual"); 13 | } 14 | }); 15 | Ok(()) 16 | } 17 | -------------------------------------------------------------------------------- /src/cmd/mod.rs: -------------------------------------------------------------------------------- 1 | use lazy_static::lazy_static; 2 | use rustc_hash::FxHashMap; 3 | 4 | pub mod cat; 5 | pub mod check; 6 | pub mod fs_handle; 7 | pub mod grep; 8 | pub mod man; 9 | 10 | pub use fs_handle::*; 11 | 12 | type ProgResult = Result<(), Box>; 13 | type Prog = fn(&[String]) -> ProgResult; 14 | 15 | macro_rules! impl_cmd { 16 | ($hmp:tt, $($cmd:tt), *) => { 17 | $( 18 | $hmp.insert(stringify!($cmd), $cmd::$cmd); 19 | )* 20 | } 21 | } 22 | 23 | lazy_static! { 24 | pub static ref COMMANDS: FxHashMap<&'static str, Prog> = { 25 | let mut hmp: FxHashMap<&'static str, Prog> = FxHashMap::default(); 26 | impl_cmd!(hmp, cat, man, grep, rm, can, touch, rmdir, mkdir, ls, cp, check); 27 | hmp 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod cmd; 2 | pub mod man; 3 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::{env, process}; 2 | use std::error::Error; 3 | use tct::cmd::COMMANDS; 4 | 5 | fn main() -> Result<(), Box> { 6 | let args: Vec = env::args().collect(); 7 | COMMANDS 8 | .get(args.get(1).unwrap_or_else(|| { 9 | eprintln!("need to pass an argument"); 10 | process::exit(1); 11 | }).as_str()) 12 | .unwrap_or_else(|| { 13 | eprintln!("{} isn't a valid command", args[1]); 14 | process::exit(1); 15 | })(&args[1..]) 16 | } 17 | -------------------------------------------------------------------------------- /src/man/README.md: -------------------------------------------------------------------------------- 1 | # Manual pages 2 | Used by `man` command to show documentation about it. 3 | 4 | ## Adding 5 | Just create a file with the same command name. In `src/cmd/mod.rs` (line 38), add a new argument containing the filename as a `&str` string; 6 | 7 | ### Manpages status 8 | - [ ] (can) 9 | - [ ] (mkdir) 10 | - [ ] (rm) 11 | - [ ] (rmdir) 12 | - [ ] (touch) 13 | - [X] (cat) 14 | - [ ] (grep) 15 | - [X] (man) 16 | -------------------------------------------------------------------------------- /src/man/cat: -------------------------------------------------------------------------------- 1 | Prints files on STDOUT 2 | 3 | Args: 4 | [FILE1, FILE2, FILE3, ...] 5 | Files to be printed 6 | 7 | Ex: `cat some_file.txt` 8 | -------------------------------------------------------------------------------- /src/man/fs_handle/can: -------------------------------------------------------------------------------- 1 | Shows the canonical path form of a file 2 | 3 | Args: 4 | [FILE1, FILE2, FILE3, ...] 5 | Files to have their absolute path printed 6 | 7 | Ex: `can some_file.txt` 8 | -------------------------------------------------------------------------------- /src/man/fs_handle/cp: -------------------------------------------------------------------------------- 1 | Copies files 2 | 3 | Args: 4 | [(FROM_FILE_PATH1, TO_FILE_PATH1), (FROM_FILE_PATH2, TO_FILE_PATH2), (FROM_FILE_PATH3, TO_FILE_PATH3), ...] 5 | Files to be copied. `FROM` being the original file and `TO` the new file. 6 | 7 | Ex: `cp some_file.txt some_copy.txt` 8 | -------------------------------------------------------------------------------- /src/man/fs_handle/cpdir: -------------------------------------------------------------------------------- 1 | Copies folders 2 | 3 | Args: 4 | [(FROM_FOLDER_PATH1, TO_FOLDER_PATH1), (FROM_FOLDER_PATH2, TO_FOLDER_PATH2), (FROM_FOLDER_PATH3, TO_FOLDER_PATH3), ...] 5 | Folders to be copied. `FROM` being the original folder and `TO` the new folder. 6 | 7 | Ex: `cpdir some_dir some_copied_dir` 8 | -------------------------------------------------------------------------------- /src/man/fs_handle/ls: -------------------------------------------------------------------------------- 1 | Show all files and folders from the entered paths 2 | 3 | Args: 4 | [FOLDER_PATH1, FOLDER_PATH2, FOLDER_PATH3, ...] 5 | Folders to be listed 6 | 7 | Ex: `ls .` 8 | -------------------------------------------------------------------------------- /src/man/fs_handle/mkdir: -------------------------------------------------------------------------------- 1 | Creates folders 2 | 3 | Args: 4 | [FOLDER_NAME1, FOLDER_NAME2, FOLDER_NAME3, ...] 5 | The name of the folders to be created 6 | 7 | Ex: `mkdir some_dir` 8 | -------------------------------------------------------------------------------- /src/man/fs_handle/rm: -------------------------------------------------------------------------------- 1 | Removes files 2 | 3 | Args: 4 | [FILE1, FILE2, FILE3, ...] 5 | Files to be removed 6 | 7 | Ex: `rm some_file.txt` 8 | -------------------------------------------------------------------------------- /src/man/fs_handle/rmdir: -------------------------------------------------------------------------------- 1 | Removes folders 2 | 3 | Args: 4 | [FOLDER_NAME1, FOLDER_NAME2, FOLDER_NAME3, ...] 5 | Folders to be removed 6 | 7 | Ex: `rmdir some_dir` 8 | -------------------------------------------------------------------------------- /src/man/fs_handle/touch: -------------------------------------------------------------------------------- 1 | Creates files 2 | 3 | Args: 4 | [FILES1, FILES2, FILES3, ...] 5 | Files to be created 6 | 7 | Ex: `touch some_file.txt` 8 | -------------------------------------------------------------------------------- /src/man/grep: -------------------------------------------------------------------------------- 1 | Researches by a string within past files 2 | 3 | Args: 4 | [PATTERN] 5 | String to be searched 6 | [FILE1, FILE2, FILE3, ...] 7 | Files to be considered 8 | 9 | Ex: `grep email ~/.gitconfig` 10 | -------------------------------------------------------------------------------- /src/man/man: -------------------------------------------------------------------------------- 1 | Shows the manualpage for each command entered 2 | 3 | Args: 4 | [CMD1, CMD2, CMD3, ...] 5 | Print the manual command from `man/` 6 | 7 | Ex: `man cat` 8 | -------------------------------------------------------------------------------- /src/man/mod.rs: -------------------------------------------------------------------------------- 1 | use lazy_static::lazy_static; 2 | use rustc_hash::FxHashMap; 3 | 4 | type ManualMap = FxHashMap<&'static str, &'static str>; 5 | 6 | macro_rules! impl_man { 7 | ($hmp:tt, $($cmd:tt), *) => { 8 | $( 9 | $hmp.insert($cmd, $cmd).unwrap(); 10 | )* 11 | } 12 | } 13 | 14 | lazy_static! { 15 | pub static ref MANUALS: ManualMap = { 16 | let mut hmp: ManualMap = ManualMap::default(); 17 | impl_man!( 18 | hmp, 19 | "cat", 20 | "man", 21 | "grei", 22 | "fs_handle/can", 23 | "fs_handle/cp", 24 | "fs_handle/cpdir", 25 | "fs_handle/ls", 26 | "fs_handle/mkdir", 27 | "fs_handle/rm", 28 | "fs_handle/rmdir", 29 | "fs_handle/touch" 30 | ); 31 | hmp 32 | }; 33 | } 34 | --------------------------------------------------------------------------------