init
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
/result*
|
||||||
69
Cargo.lock
generated
Normal file
69
Cargo.lock
generated
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayvec"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg_aliases"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.180"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.30.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cfg-if",
|
||||||
|
"cfg_aliases",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustty"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"nix",
|
||||||
|
"vte",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vte"
|
||||||
|
version = "0.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5924018406ce0063cd67f8e008104968b74b563ee1b85dde3ed1f7cb87d3dbd"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "rustty"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
nix = {default-features = false, features=["term","process","fs"], version="0.30.1"}
|
||||||
|
vte = "0.15.0"
|
||||||
87
flake.lock
generated
Normal file
87
flake.lock
generated
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"fenix": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"naersk",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1752475459,
|
||||||
|
"narHash": "sha256-z6QEu4ZFuHiqdOPbYss4/Q8B0BFhacR8ts6jO/F/aOU=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"rev": "bf0d6f70f4c9a9cf8845f992105652173f4b617f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"naersk": {
|
||||||
|
"inputs": {
|
||||||
|
"fenix": "fenix",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1763384566,
|
||||||
|
"narHash": "sha256-r+wgI+WvNaSdxQmqaM58lVNvJYJ16zoq+tKN20cLst4=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "naersk",
|
||||||
|
"rev": "d4155d6ebb70fbe2314959842f744aa7cabbbf6a",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "naersk",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1768305791,
|
||||||
|
"narHash": "sha256-AIdl6WAn9aymeaH/NvBj0H9qM+XuAuYbGMZaP0zcXAQ=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "1412caf7bf9e660f2f962917c14b1ea1c3bc695e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"naersk": "naersk",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-analyzer-src": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1752428706,
|
||||||
|
"narHash": "sha256-EJcdxw3aXfP8Ex1Nm3s0awyH9egQvB2Gu+QEnJn2Sfg=",
|
||||||
|
"owner": "rust-lang",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"rev": "591e3b7624be97e4443ea7b5542c191311aa141d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "rust-lang",
|
||||||
|
"ref": "nightly",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
23
flake.nix
Normal file
23
flake.nix
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "nixpkgs/nixos-unstable";
|
||||||
|
naersk = {
|
||||||
|
url = "github:nix-community/naersk";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
outputs = {
|
||||||
|
nixpkgs,
|
||||||
|
naersk,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
system = "x86_64-linux";
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
in {
|
||||||
|
packages.${system} = {
|
||||||
|
default = pkgs.callPackage ./package.nix {
|
||||||
|
naersk = pkgs.callPackage naersk {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
38
package.nix
Normal file
38
package.nix
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
fontconfig,
|
||||||
|
freetype,
|
||||||
|
lib,
|
||||||
|
libGL,
|
||||||
|
libxkbcommon,
|
||||||
|
makeWrapper,
|
||||||
|
naersk,
|
||||||
|
pkg-config,
|
||||||
|
wayland,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
naersk.buildPackage rec {
|
||||||
|
name = "rustty";
|
||||||
|
src = ./.;
|
||||||
|
buildInputs = [
|
||||||
|
# fonts
|
||||||
|
fontconfig
|
||||||
|
freetype
|
||||||
|
freetype.dev
|
||||||
|
|
||||||
|
# wayland graphics
|
||||||
|
libGL
|
||||||
|
libxkbcommon
|
||||||
|
wayland
|
||||||
|
];
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkg-config
|
||||||
|
makeWrapper
|
||||||
|
];
|
||||||
|
postInstall = ''
|
||||||
|
wrapProgram "$out/bin/${meta.mainProgram}" --prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath buildInputs}"
|
||||||
|
'';
|
||||||
|
meta = {
|
||||||
|
mainProgram = "rustty";
|
||||||
|
homepage = "https://mtgmonkey.net";
|
||||||
|
};
|
||||||
|
}
|
||||||
98
src/main.rs
Normal file
98
src/main.rs
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
use nix::pty::{ForkptyResult, forkpty, PtyMaster};
|
||||||
|
use nix::unistd::read;
|
||||||
|
|
||||||
|
use std::vec::Vec;
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
|
use std::process::Command;
|
||||||
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use vte::{Params, Parser, Perform};
|
||||||
|
|
||||||
|
struct Performer;
|
||||||
|
impl Perform for Performer {
|
||||||
|
fn print(&mut self, c: char) {
|
||||||
|
println!("[print] {:?}", c);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute(&mut self, byte: u8) {
|
||||||
|
println!("[execute] {:02x}", byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hook(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: char) {
|
||||||
|
println!(
|
||||||
|
"[hook] params={:?}, intermediates={:?}, ignore={:?}, char={:?}",
|
||||||
|
params, intermediates, ignore, c
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn put(&mut self, byte: u8) {
|
||||||
|
println!("[put] {:02x}", byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unhook(&mut self) {
|
||||||
|
println!("[unhook]");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) {
|
||||||
|
println!("[osc_dispatch] params={:?} bell_terminated={}", params, bell_terminated);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn csi_dispatch(&mut self, params: &Params, intermediates: &[u8], ignore: bool, c: char) {
|
||||||
|
println!(
|
||||||
|
"[csi_dispatch] params={:#?}, intermediates={:?}, ignore={:?}, char={:?}",
|
||||||
|
params, intermediates, ignore, c
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn esc_dispatch(&mut self, intermediates: &[u8], ignore: bool, byte: u8) {
|
||||||
|
println!(
|
||||||
|
"[esc_dispatch] intermediates={:?}, ignore={:?}, byte={:02x}",
|
||||||
|
intermediates, ignore, byte
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
|
||||||
|
// TODO get rid of hard coded `sh` path
|
||||||
|
let mut pty = spawn_pty("/home/andromeda/.nix-profile/bin/sh").unwrap();
|
||||||
|
println!("{:?}", &pty);
|
||||||
|
|
||||||
|
let input = io::stdin();
|
||||||
|
let mut handle = input.lock();
|
||||||
|
|
||||||
|
let mut statemachine = Parser::new();
|
||||||
|
let mut performer = Performer;
|
||||||
|
let mut buf = [0u8; 2048];
|
||||||
|
|
||||||
|
while true {
|
||||||
|
match read(&pty, &mut buf) {
|
||||||
|
Ok(0) => break,
|
||||||
|
Ok(n) => {
|
||||||
|
statemachine.advance(&mut performer, &buf[..n]);
|
||||||
|
},
|
||||||
|
Err(_e) => break,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// forks a new pty and returns file descriptor of the master
|
||||||
|
fn spawn_pty(shell: &str) -> Option<PtyMaster> {
|
||||||
|
// SAFETY safe unless os out of PTYs; incredibly unlikely
|
||||||
|
match unsafe {forkpty(None, None)} {
|
||||||
|
Ok(fork_pty_res) => match fork_pty_res {
|
||||||
|
ForkptyResult::Parent {master, ..} => {
|
||||||
|
// SAFETY `master` is a valid PtyMaster
|
||||||
|
return Some(unsafe{PtyMaster::from_owned_fd(master)});
|
||||||
|
}
|
||||||
|
ForkptyResult::Child =>{
|
||||||
|
Command::new(shell).spawn();
|
||||||
|
// TODO come up with an elegant solution
|
||||||
|
thread::sleep(Duration::MAX);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_e) => return None,
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user