forked from AbleOS/ableos_userland
initial userland commit
This commit is contained in:
commit
14dd080dba
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
262
Cargo.lock
generated
Normal file
262
Cargo.lock
generated
Normal file
|
@ -0,0 +1,262 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "basic_driver"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clparse"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hashbrown 0.13.1",
|
||||
"log",
|
||||
"toml 0.5.9 (git+https://git.ablecorp.us/theoddgarlic/toml-rs)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derelict_microarchitecture"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ground"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
dependencies = [
|
||||
"ahash 0.7.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038"
|
||||
dependencies = [
|
||||
"ahash 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.138"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "no_video"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ron"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bitflags",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.148"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.148"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"versioning",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.9"
|
||||
source = "git+https://git.ablecorp.us/theoddgarlic/toml-rs#34db433429f3ad38921d13ac9aba74c8a706f376"
|
||||
dependencies = [
|
||||
"hashbrown 0.12.3",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trash_manifest"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ron",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"toml 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "versioning"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vgable"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
22
Cargo.toml
Normal file
22
Cargo.toml
Normal file
|
@ -0,0 +1,22 @@
|
|||
[workspace]
|
||||
|
||||
members = [
|
||||
|
||||
"drivers/basic_driver",
|
||||
"drivers/graphics/derelict_microarchitecture",
|
||||
"drivers/graphics/ground",
|
||||
"drivers/graphics/novideo",
|
||||
"drivers/graphics/vgable",
|
||||
|
||||
"libraries/clparse",
|
||||
"libraries/tar",
|
||||
"libraries/trash_manifest",
|
||||
"libraries/versioning",
|
||||
|
||||
# "programs/delete",
|
||||
# "programs/list",
|
||||
# "programs/shell",
|
||||
# "programs/table",
|
||||
# "programs/table_view",
|
||||
# "programs/undelete",
|
||||
]
|
21
LICENSE.md
Normal file
21
LICENSE.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022 AbleCorp
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
2
drivers/basic_driver/.cargo/config.toml
Normal file
2
drivers/basic_driver/.cargo/config.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
[build]
|
||||
target = "wasm32-unknown-unknown"
|
8
drivers/basic_driver/Cargo.toml
Normal file
8
drivers/basic_driver/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "basic_driver"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
8
drivers/basic_driver/src/main.rs
Normal file
8
drivers/basic_driver/src/main.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[no_mangle]
|
||||
fn start() -> i32 {
|
||||
// Simple driver
|
||||
1
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
[build]
|
||||
target = "wasm32-unknown-unknown"
|
8
drivers/graphics/derelict_microarchitecture/Cargo.toml
Normal file
8
drivers/graphics/derelict_microarchitecture/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "derelict_microarchitecture"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
8
drivers/graphics/derelict_microarchitecture/src/main.rs
Normal file
8
drivers/graphics/derelict_microarchitecture/src/main.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[no_mangle]
|
||||
fn start() -> i32 {
|
||||
// Simple driver
|
||||
1
|
||||
}
|
2
drivers/graphics/ground/.cargo/config.toml
Normal file
2
drivers/graphics/ground/.cargo/config.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
[build]
|
||||
target = "wasm32-unknown-unknown"
|
8
drivers/graphics/ground/Cargo.toml
Normal file
8
drivers/graphics/ground/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "ground"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
8
drivers/graphics/ground/src/main.rs
Normal file
8
drivers/graphics/ground/src/main.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[no_mangle]
|
||||
fn start() -> i32 {
|
||||
// Simple driver
|
||||
1
|
||||
}
|
2
drivers/graphics/novideo/.cargo/config.toml
Normal file
2
drivers/graphics/novideo/.cargo/config.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
[build]
|
||||
target = "wasm32-unknown-unknown"
|
8
drivers/graphics/novideo/Cargo.toml
Normal file
8
drivers/graphics/novideo/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "no_video"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
8
drivers/graphics/novideo/src/main.rs
Normal file
8
drivers/graphics/novideo/src/main.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[no_mangle]
|
||||
fn start() -> i32 {
|
||||
// Simple driver
|
||||
1
|
||||
}
|
2
drivers/graphics/vgable/.cargo/config.toml
Normal file
2
drivers/graphics/vgable/.cargo/config.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
[build]
|
||||
target = "wasm32-unknown-unknown"
|
8
drivers/graphics/vgable/Cargo.toml
Normal file
8
drivers/graphics/vgable/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "vgable"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
8
drivers/graphics/vgable/src/main.rs
Normal file
8
drivers/graphics/vgable/src/main.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[no_mangle]
|
||||
fn start() -> i32 {
|
||||
// Simple driver
|
||||
1
|
||||
}
|
0
drivers/readme.md
Normal file
0
drivers/readme.md
Normal file
25
libraries/clparse/Cargo.toml
Normal file
25
libraries/clparse/Cargo.toml
Normal file
|
@ -0,0 +1,25 @@
|
|||
[package]
|
||||
name = "clparse"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = []
|
||||
|
||||
|
||||
[dependencies]
|
||||
log = "*"
|
||||
hashbrown = "*"
|
||||
|
||||
|
||||
[dependencies.toml]
|
||||
git = "https://git.ablecorp.us:443/theoddgarlic/toml-rs"
|
||||
# version = "0.5.8"
|
||||
default-features = false
|
||||
|
||||
|
||||
# [dependencies.thiserror]
|
||||
# version = "1.0"
|
||||
# default-features = false
|
17
libraries/clparse/SPEC.md
Normal file
17
libraries/clparse/SPEC.md
Normal file
|
@ -0,0 +1,17 @@
|
|||
# CLParse
|
||||
## Arguments
|
||||
An argument must be passed in the form of `abc=xyz`
|
||||
|
||||
arguments may ***NOT*** have implicit argument anywhere but the final spot and it optionally may have ***only*** one(1)
|
||||
This is different that you may be used to
|
||||
|
||||
For example; the `cat` program of unix-like machines can be called like
|
||||
|
||||
`cat abc.c xyz.c`
|
||||
|
||||
and the equivelent on ableOS would be
|
||||
|
||||
`append src=abc.c dest=xyz.c`
|
||||
|
||||
## Config
|
||||
clparse also loads configs into toml values and passes them along
|
3
libraries/clparse/assets/example.toml
Normal file
3
libraries/clparse/assets/example.toml
Normal file
|
@ -0,0 +1,3 @@
|
|||
[list]
|
||||
size = true
|
||||
last_modified = true
|
16
libraries/clparse/assets/full_system_example.toml
Normal file
16
libraries/clparse/assets/full_system_example.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[kernel]
|
||||
boot = true
|
||||
|
||||
[system]
|
||||
[system.bootloader]
|
||||
|
||||
[shared.list]
|
||||
size = true
|
||||
last_modified = true
|
||||
|
||||
[user.able.list]
|
||||
size = false
|
||||
last_modified = true
|
||||
|
||||
[user.able.shell.alias]
|
||||
ls = "list"
|
210
libraries/clparse/src/lib.rs
Normal file
210
libraries/clparse/src/lib.rs
Normal file
|
@ -0,0 +1,210 @@
|
|||
//! # clparse
|
||||
//! simple command line parser for ableOS
|
||||
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate std;
|
||||
|
||||
use hashbrown;
|
||||
use hashbrown::HashMap;
|
||||
|
||||
use alloc::string::String;
|
||||
pub use toml;
|
||||
|
||||
pub type Argmap = HashMap<String, String>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Arguments {
|
||||
pub arguments: Argmap,
|
||||
}
|
||||
|
||||
impl Arguments {
|
||||
// TODO: Maybe check if a key is truthy, like if it's value equals "true", "1", "on", etc.
|
||||
// NOTE: The above is out of scope for this pr but will be considered -able
|
||||
pub fn parse(command: String) -> Result<Arguments, CLparseErrors> {
|
||||
// TODO: Parse one implicit arg.
|
||||
// NOTE: The above is out of scope for this pr but will be considered -able
|
||||
let mut cmd = Arguments {
|
||||
arguments: HashMap::new(),
|
||||
};
|
||||
|
||||
if !command.is_empty() {
|
||||
let command_split = command.split(" ");
|
||||
for kv_pair in command_split {
|
||||
if kv_pair.contains("=") {
|
||||
// println!("{kv_pair}");
|
||||
let mut kv_split = kv_pair.split("=");
|
||||
|
||||
let key = kv_split.next().unwrap().to_string();
|
||||
// println!("{key}");
|
||||
let value = kv_split.next().unwrap().to_string();
|
||||
// println!("{value}");
|
||||
|
||||
cmd.arguments.insert(key, value);
|
||||
} else {
|
||||
return Err(CLparseErrors::MissingEquals);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(cmd)
|
||||
}
|
||||
pub fn parse_from_string<S: Into<String>>(
|
||||
string: S,
|
||||
) -> Result<(Value, Arguments), CLparseErrors> {
|
||||
let config: toml::Value = Value::String("".to_string());
|
||||
|
||||
let args = Arguments::parse(string.into())?;
|
||||
|
||||
return Ok((config, args));
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub fn parse_from_args() -> Result<(Value, Arguments), CLparseErrors> {
|
||||
use std::{
|
||||
collections::{BTreeMap, HashMap},
|
||||
env,
|
||||
fs::File,
|
||||
io::{Read, Write},
|
||||
println,
|
||||
};
|
||||
|
||||
use alloc::format;
|
||||
|
||||
let args = env::args();
|
||||
let mut args_str = String::new();
|
||||
|
||||
let dir = env::current_dir().unwrap();
|
||||
let mut config: toml::Value = Value::String("".to_string());
|
||||
match env::current_exe() {
|
||||
Ok(bin) => {
|
||||
if let Some(exe_name) = bin.as_path().file_name() {
|
||||
let exe_name = exe_name.to_str().unwrap();
|
||||
|
||||
// println!("{exe_name}");
|
||||
|
||||
let path = format!(
|
||||
"/home/{}/configs/{}/config.toml",
|
||||
env::var("USER").unwrap(),
|
||||
exe_name
|
||||
);
|
||||
let path = std::path::Path::new(&path);
|
||||
if path.exists() {
|
||||
let display = path.display();
|
||||
|
||||
let mut file = match File::open(&path) {
|
||||
Err(why) => panic!("couldn't open {}: {}", display, why),
|
||||
Ok(file) => file,
|
||||
};
|
||||
|
||||
let mut s = String::new();
|
||||
match file.read_to_string(&mut s) {
|
||||
Err(why) => panic!("couldn't read {}: {}", display, why),
|
||||
Ok(_) => {
|
||||
// print!("{} contains:\n{}", display, s)
|
||||
}
|
||||
}
|
||||
|
||||
config = toml::from_str(&s).unwrap();
|
||||
} else {
|
||||
let mut file = File::create(path);
|
||||
|
||||
println!("Make a file in your home dir called \"configs\"");
|
||||
|
||||
file.unwrap().write_all(b"Hello, world!").unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => todo!(),
|
||||
}
|
||||
|
||||
for (count, arg) in args.enumerate() {
|
||||
if count == 0 || count == 1 {
|
||||
// Ignore stdio + program name on unix
|
||||
} else {
|
||||
args_str.push_str(&arg);
|
||||
args_str.push(' ');
|
||||
}
|
||||
}
|
||||
// needed to remove the very last ` ` which is unneeded
|
||||
args_str.pop();
|
||||
// println!("{args_str}");
|
||||
|
||||
let ret = Arguments::parse(args_str)?;
|
||||
return Ok((config, ret));
|
||||
}
|
||||
|
||||
pub fn is_truthy(&self, key: &str) -> bool {
|
||||
match self.arguments.get(key) {
|
||||
Some(val) => {
|
||||
let val = val.to_lowercase();
|
||||
if val == "true" || val == "1" || val == "on" || val == "t" {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CLparseErrors {
|
||||
MalformendArgument,
|
||||
MissingEquals,
|
||||
}
|
||||
|
||||
impl Display for CLparseErrors {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "{:?}", self)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
use core::fmt::Display;
|
||||
|
||||
use crate::alloc::string::ToString;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
#[test]
|
||||
#[cfg(feature = "std")]
|
||||
fn test_arg_parse() {
|
||||
use std::println;
|
||||
let argline = "abc=xyz".to_string();
|
||||
|
||||
match Arguments::parse(argline) {
|
||||
Ok(ok) => {
|
||||
println!("{ok:?}")
|
||||
}
|
||||
Err(err) => panic!("{err:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fail_test_arg_parse() {
|
||||
let argline = "abcxyz".to_string();
|
||||
|
||||
match Arguments::parse(argline) {
|
||||
Ok(ok) => panic!("{ok:?}"),
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use toml::Value;
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "std")]
|
||||
pub fn load_config() {
|
||||
use std::println;
|
||||
|
||||
let toml_str = include_str!("../assets/example.toml");
|
||||
|
||||
let decoded: Value = toml::from_str(toml_str).unwrap();
|
||||
println!("{}", decoded);
|
||||
}
|
9
libraries/tar/Cargo.toml
Normal file
9
libraries/tar/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "tar"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
versioning = { path = "../versioning" }
|
3
libraries/tar/readme.md
Normal file
3
libraries/tar/readme.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Tar
|
||||
instead of using the sortform name for tar we will be using full names
|
||||
`mtime` becomes `modified_time`
|
55
libraries/tar/src/lib.rs
Normal file
55
libraries/tar/src/lib.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
#![no_std]
|
||||
pub const VERSION: versioning::Version = versioning::Version {
|
||||
major: 0,
|
||||
minor: 1,
|
||||
patch: 0,
|
||||
};
|
||||
|
||||
pub struct Header {
|
||||
pub filename: [char; 100],
|
||||
pub filemode: [char; 8],
|
||||
pub user_id: [char; 8],
|
||||
pub group_id: [char; 8],
|
||||
pub size: [char; 12],
|
||||
pub modified_time: [char; 12],
|
||||
pub checksum: [char; 8],
|
||||
pub typeflag: char,
|
||||
}
|
||||
|
||||
impl From<[char; 512]> for Header {
|
||||
fn from(item: [char; 512]) -> Self {
|
||||
let mut filename: [char; 100] = ['\0'; 100];
|
||||
filename[..100].clone_from_slice(&item[0..100]);
|
||||
|
||||
let mut filemode: [char; 8] = ['\0'; 8];
|
||||
filemode[..8].clone_from_slice(&item[100..108]);
|
||||
|
||||
let mut user_id: [char; 8] = ['\0'; 8];
|
||||
user_id[..8].clone_from_slice(&item[108..116]);
|
||||
|
||||
let mut group_id: [char; 8] = ['\0'; 8];
|
||||
group_id[..8].clone_from_slice(&item[116..124]);
|
||||
|
||||
let mut size: [char; 12] = ['\0'; 12];
|
||||
size[..12].clone_from_slice(&item[124..136]);
|
||||
|
||||
let mut modified_time: [char; 12] = ['\0'; 12];
|
||||
modified_time[..12].clone_from_slice(&item[136..148]);
|
||||
|
||||
let mut checksum: [char; 8] = ['\0'; 8];
|
||||
checksum[..8].clone_from_slice(&item[148..154]);
|
||||
|
||||
let typeflag: char = item[155];
|
||||
|
||||
Self {
|
||||
filename,
|
||||
filemode,
|
||||
user_id,
|
||||
group_id,
|
||||
size,
|
||||
modified_time,
|
||||
checksum,
|
||||
typeflag,
|
||||
}
|
||||
}
|
||||
}
|
12
libraries/trash_manifest/Cargo.toml
Normal file
12
libraries/trash_manifest/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "trash_manifest"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
toml = "0.5"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
thiserror = "1.0"
|
||||
ron = "0.7"
|
76
libraries/trash_manifest/src/lib.rs
Normal file
76
libraries/trash_manifest/src/lib.rs
Normal file
|
@ -0,0 +1,76 @@
|
|||
use std::fs::File;
|
||||
use std::io::{Read, Seek, Write};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||
pub struct TrashFile {
|
||||
pub name: String,
|
||||
pub origin: PathBuf,
|
||||
}
|
||||
|
||||
pub struct Manifest {
|
||||
files: Vec<TrashFile>,
|
||||
manifest: File,
|
||||
}
|
||||
|
||||
impl Manifest {
|
||||
/// Creates a new Manifest from a .manifest.ron file.
|
||||
/// Expects File to be read and write.
|
||||
pub fn new(mut manifest: File) -> Result<Self, TrashManifestError> {
|
||||
let mut contents = String::new();
|
||||
manifest.read_to_string(&mut contents)?;
|
||||
manifest.rewind()?;
|
||||
|
||||
if contents.len() < 2 {
|
||||
contents = "[]".to_string();
|
||||
}
|
||||
let files: Vec<TrashFile> = ron::from_str(&contents)?;
|
||||
Ok(Self { files, manifest })
|
||||
}
|
||||
|
||||
/// Get a certain file from the manifest by it's name.
|
||||
pub fn get(&self, name: String) -> Option<TrashFile> {
|
||||
self.files
|
||||
.iter()
|
||||
.find(|file| file.name == *name)
|
||||
.map(|file| file.clone())
|
||||
}
|
||||
|
||||
/// Get a clone of the underlying Vec of TrashFile.
|
||||
pub fn get_all(&self) -> Vec<TrashFile> {
|
||||
self.files.clone()
|
||||
}
|
||||
|
||||
/// Remove a file from the manifest by it's name.
|
||||
/// Consumes self and returns self back in a result to prevent inconsistencies
|
||||
/// between self and the actual manifest file in case of Err.
|
||||
pub fn remove(mut self, name: String) -> Result<Self, TrashManifestError> {
|
||||
self.files.retain(|file| file.name != name);
|
||||
let contents = ron::to_string(&self.files)?;
|
||||
self.manifest.set_len(0)?;
|
||||
self.manifest.rewind()?;
|
||||
write!(&mut self.manifest, "{}", contents)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Add a file to the manifest by it's name and path to origin.
|
||||
/// Consumes self and returns self back in a result to prevent inconsistencies
|
||||
/// between self and the actual manifest file in case of Err.
|
||||
pub fn add(mut self, name: String, origin: PathBuf) -> Result<Self, TrashManifestError> {
|
||||
self.files.push(TrashFile { name, origin });
|
||||
dbg!(&self.files);
|
||||
let contents = ron::to_string(&self.files)?;
|
||||
self.manifest.set_len(0)?;
|
||||
self.manifest.rewind()?;
|
||||
write!(&mut self.manifest, "{}", contents)?;
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum TrashManifestError {
|
||||
#[error("Could not read manifest file")]
|
||||
IoError(#[from] std::io::Error),
|
||||
#[error("Could not serialize or deserialize manifest file")]
|
||||
SerializationError(#[from] ron::Error),
|
||||
}
|
12
libraries/versioning/Cargo.toml
Normal file
12
libraries/versioning/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "versioning"
|
||||
version = "0.1.2"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
default-features = false
|
||||
features = ["derive"]
|
45
libraries/versioning/src/lib.rs
Normal file
45
libraries/versioning/src/lib.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
// ! A unified versioning system for Rust.
|
||||
#![no_std]
|
||||
use core::{fmt::Display, prelude::rust_2021::derive};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct Version {
|
||||
pub major: u8,
|
||||
pub minor: u8,
|
||||
pub patch: u8,
|
||||
}
|
||||
|
||||
impl Version {
|
||||
pub fn new(major: u8, minor: u8, patch: u8) -> Self {
|
||||
Self {
|
||||
major,
|
||||
minor,
|
||||
patch,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_env(vstring: &'static str) -> Self {
|
||||
let mut spl = vstring.split(".");
|
||||
if spl.clone().count() > 3 {
|
||||
panic!("Improper version string");
|
||||
}
|
||||
// TODO: handle failing any of these
|
||||
let major: u8 = spl.nth(0).unwrap().parse().unwrap();
|
||||
let minor: u8 = spl.nth(1).unwrap().parse().unwrap();
|
||||
let patch: u8 = spl.nth(2).unwrap().parse().unwrap();
|
||||
|
||||
Self {
|
||||
major,
|
||||
minor,
|
||||
patch,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Version {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, "v{}.{}.{}", self.major, self.minor, self.patch)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
12
programs/delete/Cargo.toml
Normal file
12
programs/delete/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "delete"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clparse = { path = "../clparse", features = ["std"] }
|
||||
trash_manifest = { path = "../trash_manifest" }
|
||||
anyhow = "1.0"
|
||||
fs_extra = "1.2"
|
15
programs/delete/README.md
Normal file
15
programs/delete/README.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
# delete
|
||||
|
||||
Moves a file to your .trash directory and updates the .manifest file therein.
|
||||
|
||||
## Usage
|
||||
|
||||
Remove file:
|
||||
|
||||
* `delete path=foobar.txt`
|
||||
* `delete p=foobar.txt`
|
||||
|
||||
Remove directory:
|
||||
|
||||
* `delete path=foobar/ dir=true`
|
||||
* `delete path=foobar/ d=t`
|
9
programs/delete/assets/config.toml
Normal file
9
programs/delete/assets/config.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
|
||||
# // - Always permanently delete files,
|
||||
bypass_trash = true
|
||||
# // - Set .trash path.
|
||||
trashpath = "/home/user/.trash"
|
||||
|
||||
# // TODO: Configuration options in programs config file:
|
||||
# // - Handle naming collisions by changing file name instead of erroring,
|
66
programs/delete/src/main.rs
Normal file
66
programs/delete/src/main.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
use fs_extra::{dir, file};
|
||||
|
||||
use std::env;
|
||||
use std::fs::OpenOptions;
|
||||
use std::path::PathBuf;
|
||||
|
||||
// TODO: Configuration options in programs config file:
|
||||
// - Always permanently delete files,
|
||||
// - Handle naming collisions by changing file name instead of erroring,
|
||||
// - Set .trash path.
|
||||
|
||||
// TODO: Option to permanently delete file.
|
||||
// TODO: .trash path option.
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let ret = clparse::Arguments::parse_from_args()?;
|
||||
let args = ret.1;
|
||||
|
||||
let trash_path = env::var("HOME")? + "/.trash/";
|
||||
let from = PathBuf::from({
|
||||
let p = args.arguments.get("p");
|
||||
let path = args.arguments.get("path");
|
||||
match (p, path) {
|
||||
(None, None) => anyhow::bail!("No path specified"),
|
||||
(None, Some(path)) => path,
|
||||
(Some(path), None) => path,
|
||||
(Some(_), Some(_)) => anyhow::bail!("Option p and path conflict"),
|
||||
}
|
||||
})
|
||||
.canonicalize()?;
|
||||
let name = from
|
||||
.file_name()
|
||||
.map(|name| name.to_str())
|
||||
.flatten()
|
||||
.ok_or(anyhow::anyhow!("Weird file name"))?;
|
||||
let manifest = trash_manifest::Manifest::new(
|
||||
OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.read(true)
|
||||
.open(trash_path.clone() + ".manifest.ron")?,
|
||||
)?;
|
||||
let is_in_trash = if from.to_string_lossy() == trash_path.clone() + name {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
match (
|
||||
is_in_trash,
|
||||
args.arguments.get("dir").is_some() || args.arguments.get("d").is_some(),
|
||||
) {
|
||||
(true, true) => fs_extra::dir::remove(from.clone())?,
|
||||
(true, false) => fs_extra::file::remove(from.clone())?,
|
||||
(false, true) => {
|
||||
fs_extra::dir::move_dir(from.clone(), trash_path + name, &dir::CopyOptions::new())?;
|
||||
}
|
||||
(false, false) => {
|
||||
fs_extra::file::move_file(from.clone(), trash_path + name, &file::CopyOptions::new())?;
|
||||
}
|
||||
}
|
||||
if !is_in_trash {
|
||||
manifest.add(name.to_string(), from.clone())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
11
programs/list/Cargo.toml
Normal file
11
programs/list/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "list"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clparse = { path = "../clparse" }
|
||||
number_prefix = "*"
|
||||
table = { path = "../table" }
|
95
programs/list/src/main.rs
Normal file
95
programs/list/src/main.rs
Normal file
|
@ -0,0 +1,95 @@
|
|||
use std::{collections::HashMap, env, fs};
|
||||
|
||||
use number_prefix::NumberPrefix;
|
||||
use table::{Row, Table};
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
let ret = clparse::Arguments::parse_from_args().unwrap();
|
||||
let args = ret.1;
|
||||
|
||||
let mut table = Table {
|
||||
table: HashMap::new(),
|
||||
};
|
||||
|
||||
let current_dir = env::current_dir()?;
|
||||
|
||||
let size_shown = args.is_truthy("s");
|
||||
|
||||
let last_modified_shown = args.is_truthy("lm");
|
||||
|
||||
let row = Row(vec![], 20);
|
||||
table.table.insert("File Name".to_string(), row);
|
||||
|
||||
if size_shown {
|
||||
let row = Row(vec![], 20);
|
||||
table.table.insert("Size".to_string(), row);
|
||||
}
|
||||
|
||||
if last_modified_shown {
|
||||
let row = Row(vec![], 20);
|
||||
table.table.insert("Last Modified".to_string(), row);
|
||||
}
|
||||
|
||||
for entry in fs::read_dir(current_dir)? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
|
||||
let metadata = fs::metadata(&path)?;
|
||||
|
||||
let abc = table.table.get_mut(&"File Name".to_string());
|
||||
let mut path = format!(
|
||||
"{}",
|
||||
path.file_name()
|
||||
.ok_or("No filename")
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
);
|
||||
if metadata.is_dir() {
|
||||
path.push('/')
|
||||
}
|
||||
|
||||
match abc {
|
||||
Some(row) => row.0.push(path),
|
||||
None => todo!(),
|
||||
}
|
||||
|
||||
if size_shown {
|
||||
let size = metadata.len();
|
||||
|
||||
let abc = table.table.get_mut(&"Size".to_string());
|
||||
match abc {
|
||||
Some(row) => row.0.push(maybe_bytes_suffix(size)),
|
||||
None => todo!(),
|
||||
}
|
||||
}
|
||||
if last_modified_shown {
|
||||
let last_modified = metadata.modified()?.elapsed().unwrap().as_secs();
|
||||
|
||||
let abc = table.table.get_mut(&"Last Modified".to_string());
|
||||
match abc {
|
||||
Some(row) => row.0.push(format!("{} seconds ago", last_modified)),
|
||||
None => todo!(),
|
||||
}
|
||||
|
||||
// print!(" {} seconds ago |", last_modified);
|
||||
}
|
||||
|
||||
print!("\n");
|
||||
}
|
||||
|
||||
println!("{}", table);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn maybe_bytes_suffix(amount: u64) -> String {
|
||||
return match NumberPrefix::binary(amount as f64) {
|
||||
NumberPrefix::Standalone(bytes) => {
|
||||
format!("{}B", bytes)
|
||||
}
|
||||
NumberPrefix::Prefixed(prefix, n) => {
|
||||
format!("{:.1} {}B", n, prefix.symbol())
|
||||
}
|
||||
};
|
||||
}
|
9
programs/shell/Cargo.toml
Normal file
9
programs/shell/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "shell"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clparse = { path = "../clparse" }
|
2
programs/shell/assets/config.toml
Normal file
2
programs/shell/assets/config.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
[alias]
|
||||
ls = "list"
|
57
programs/shell/src/main.rs
Normal file
57
programs/shell/src/main.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
use std::{
|
||||
env,
|
||||
io::{stdin, stdout, Read, Write},
|
||||
path::Path,
|
||||
process::{Child, Command, Stdio},
|
||||
};
|
||||
|
||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
fn main() {
|
||||
let ret = clparse::Arguments::parse_from_args().unwrap();
|
||||
let config = ret.0;
|
||||
|
||||
// println!("{}", config);
|
||||
|
||||
loop {
|
||||
// use the `>` character as the prompt
|
||||
// need to explicitly flush this to ensure it prints before read_line
|
||||
print!("{} ~> ", std::env::current_dir().unwrap().display());
|
||||
stdout().flush().unwrap();
|
||||
let mut input = String::new();
|
||||
stdin().read_line(&mut input).unwrap();
|
||||
print!("{}", input);
|
||||
|
||||
let mut in_qoute = false;
|
||||
let mut building_command = String::new();
|
||||
let mut command_chain: Vec<String> = vec![];
|
||||
|
||||
for x in input.chars() {
|
||||
if x == '"' {
|
||||
in_qoute = !in_qoute;
|
||||
}
|
||||
|
||||
if x == '+' || x == '\n' {
|
||||
if !in_qoute {
|
||||
command_chain.push(building_command.trim().to_string());
|
||||
|
||||
building_command = String::new();
|
||||
}
|
||||
} else {
|
||||
building_command.push(x);
|
||||
}
|
||||
}
|
||||
|
||||
for mut command in command_chain {
|
||||
let abc = config.get("alias");
|
||||
for x in abc.unwrap().as_table().unwrap() {
|
||||
if command == *x.0 {
|
||||
command = (*x.1).to_string();
|
||||
command.remove(0);
|
||||
command.pop();
|
||||
}
|
||||
}
|
||||
|
||||
println!("Command: {}", command);
|
||||
}
|
||||
}
|
||||
}
|
8
programs/table/Cargo.toml
Normal file
8
programs/table/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "table"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
19
programs/table/README.md
Normal file
19
programs/table/README.md
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Table
|
||||
|
||||
a table is a data structure similar to a 2d array with rows and coloumns
|
||||
for example a list of files could be passed as a table to copy
|
||||
|
||||
using the following command you can generate a table
|
||||
|
||||
`list s=t e=t` which is shorthand for `list size=true executable=true`
|
||||
|
||||
> To generate a similar table use [this website](https://www.tablesgenerator.com/text_tables)
|
||||
|
||||
|file name|file size|executable|
|
||||
|-------- |---------|----------|
|
||||
|able.txt |54 |false |
|
||||
|ex.wasm |34 |true |
|
||||
|
||||
using the following command you can merge all files into one
|
||||
|
||||
`list s=t e=t + append dest=all.txt`
|
80
programs/table/src/lib.rs
Normal file
80
programs/table/src/lib.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
use core::fmt::Display;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub type Header = String;
|
||||
#[derive(Debug)]
|
||||
pub struct Row(pub Vec<String>, pub usize);
|
||||
|
||||
impl Display for Row {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// let header = &self.0;
|
||||
let column = &self.0;
|
||||
let longest_length = &self.1;
|
||||
|
||||
// write!(f, "{}", header)?;
|
||||
// for _ in 0..longest_length - header.len() {
|
||||
// write!(f, " ")?;
|
||||
// }
|
||||
// write!(f, "|\n")?;
|
||||
// for _ in 0..*longest_length {
|
||||
// write!(f, "-")?;
|
||||
// }
|
||||
|
||||
// write!(f, "|\n")?;
|
||||
for xys in column {
|
||||
write!(f, "{}", xys)?;
|
||||
for _ in 0..longest_length - xys.len() {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
write!(f, "|\n")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Table {
|
||||
pub table: HashMap<Header, Row>,
|
||||
}
|
||||
|
||||
impl Display for Table {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for (header, row) in &self.table {
|
||||
write!(f, "{}", header)?;
|
||||
for _ in 0..row.1 - header.len() {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
write!(f, "|\n")?;
|
||||
for _ in 0..row.1 {
|
||||
write!(f, "-")?;
|
||||
}
|
||||
|
||||
write!(f, "|\n")?;
|
||||
|
||||
write!(f, "{}", row)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_print() {
|
||||
let tbl = Table {
|
||||
table: HashMap::new(),
|
||||
};
|
||||
/* tbl.table.append(&mut vec![Row(
|
||||
"header".to_string(),
|
||||
vec![
|
||||
"hi".to_string(),
|
||||
"hey whats up there".to_string(),
|
||||
"hey".to_string(),
|
||||
"whats".to_string(),
|
||||
"up".to_string(),
|
||||
"there".to_string(),
|
||||
],
|
||||
18,
|
||||
)]);
|
||||
*/
|
||||
println!("{}", tbl);
|
||||
}
|
9
programs/table_view/Cargo.toml
Normal file
9
programs/table_view/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "table_view"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
table = { path = "../table" }
|
19
programs/table_view/src/main.rs
Normal file
19
programs/table_view/src/main.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use table::{Row, Table};
|
||||
|
||||
fn main() {
|
||||
let mut tbl = Table {
|
||||
table: HashMap::new(),
|
||||
};
|
||||
tbl.table.insert(
|
||||
"Example".to_string(),
|
||||
Row(
|
||||
// "header".to_string(),
|
||||
vec!["hi".to_string(), "hey whats up there".to_string()],
|
||||
19,
|
||||
),
|
||||
);
|
||||
|
||||
println!("{}", tbl);
|
||||
}
|
12
programs/undelete/Cargo.toml
Normal file
12
programs/undelete/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "undelete"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clparse = { path = "../clparse" }
|
||||
trash_manifest = { path = "../trash_manifest" }
|
||||
anyhow = "1.0"
|
||||
fs_extra = "1.2"
|
20
programs/undelete/README.md
Normal file
20
programs/undelete/README.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
# undelete
|
||||
|
||||
Moves a file from your .trash directory to current directory then updates the .manifest file.
|
||||
|
||||
## Usage
|
||||
|
||||
List deleted files:
|
||||
|
||||
* `undelete list=true`
|
||||
* `undelete l=t`
|
||||
|
||||
Undelete file or directory:
|
||||
|
||||
* `undelete name=foobar.txt`
|
||||
* `undelete n=foobar.txt`
|
||||
|
||||
Move to original location instead:
|
||||
|
||||
* `undelete name=foobar.txt origin=true`
|
||||
* `undelete name=foobar.txt o=t`
|
55
programs/undelete/src/main.rs
Normal file
55
programs/undelete/src/main.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
use std::{env, fs::OpenOptions, path::PathBuf};
|
||||
|
||||
use fs_extra::{dir, file};
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let ret = clparse::Arguments::parse_from_args()?;
|
||||
let args = ret.1;
|
||||
|
||||
let trash_path = env::var("HOME")? + "/.trash/";
|
||||
let manifest = trash_manifest::Manifest::new(
|
||||
OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.read(true)
|
||||
.open(trash_path.clone() + ".manifest.ron")?,
|
||||
)?;
|
||||
|
||||
if !args.is_truthy("list") || !args.is_truthy("l") {
|
||||
let name = {
|
||||
let n = args.arguments.get("n");
|
||||
let name = args.arguments.get("name");
|
||||
match (n, name) {
|
||||
(None, None) => anyhow::bail!("No name or operation specified"),
|
||||
(None, Some(name)) => name,
|
||||
(Some(name), None) => name,
|
||||
(Some(_), Some(_)) => anyhow::bail!("Option n and name conflict"),
|
||||
}
|
||||
};
|
||||
let file = manifest
|
||||
.get(name.to_string())
|
||||
.ok_or(anyhow::anyhow!("File not found in trash manifest"))?;
|
||||
let from = PathBuf::from(trash_path.clone() + &file.name);
|
||||
let to = if args.is_truthy("origin") || args.is_truthy("o") {
|
||||
file.origin
|
||||
} else {
|
||||
env::current_dir()?
|
||||
};
|
||||
|
||||
if from.is_dir() {
|
||||
fs_extra::dir::move_dir(from, &to, &dir::CopyOptions::new())?;
|
||||
} else {
|
||||
fs_extra::file::move_file(from, &to, &file::CopyOptions::new())?;
|
||||
}
|
||||
|
||||
manifest.remove(file.name.clone())?;
|
||||
} else {
|
||||
let mut output = String::new();
|
||||
for file in manifest.get_all() {
|
||||
output.push_str(&(file.name + "\n"));
|
||||
}
|
||||
println!("{}", output);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in a new issue