Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
epilys committed Aug 31, 2019
0 parents commit 31bf144
Show file tree
Hide file tree
Showing 23 changed files with 10,886 additions and 0 deletions.
25 changes: 25 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
target/
**/*.rs.bk
Cargo.lock
target/
**/*.rs.bk
target/
**/*.rs.bk
.gdb_history
*.log


#Added by cargo
#
#already existing elements are commented out

/target
#**/*.rs.bk


#Added by cargo
#
#already existing elements are commented out

#/target
#**/*.rs.bk
674 changes: 674 additions & 0 deletions COPYING

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "bb"
version = "0.1.0"
authors = ["Manos Pitsidianakis <[email protected]>"]
edition = "2018"
build = "build.rs"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[[bin]]
name = "bb"
path = "src/main.rs"

[dependencies]
crossbeam = "0.7"
signal-hook = "0.1.10"
termion = "1.5.3"
libc = "0.2.62"
unicode-segmentation = "1.2.1"
nix = "0.15.0"

[profile.release]
opt-level = 'z' # Optimize for size.
lto = true
codegen-units = 1
panic = 'abort'
73 changes: 73 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const LINE_BREAK_TABLE_URL: &str = "http://www.unicode.org/Public/UCD/latest/ucd/LineBreak.txt";
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::PathBuf;
use std::process::Command;

include!("src/ui/text_processing/types.rs");

fn main() -> Result<(), std::io::Error> {
let mod_path = PathBuf::from("src/ui/text_processing/tables.rs");
if mod_path.exists() {
eprintln!(
"{} already exists, delete it if you want to replace it.",
mod_path.display()
);
std::process::exit(0);
}
let mut tmpdir_path = PathBuf::from(
std::str::from_utf8(&Command::new("mktemp").arg("-d").output()?.stdout)
.unwrap()
.trim(),
);
tmpdir_path.push("LineBreak.txt");
Command::new("curl")
.args(&["-o", tmpdir_path.to_str().unwrap(), LINE_BREAK_TABLE_URL])
.output()?;

let file = File::open(&tmpdir_path)?;
let buf_reader = BufReader::new(file);

let mut line_break_table: Vec<(u32, u32, LineBreakClass)> = Vec::with_capacity(3800);
for line in buf_reader.lines() {
let line = line.unwrap();
if line.starts_with('#') || line.starts_with(' ') || line.is_empty() {
continue;
}
let tokens: &str = line.split_whitespace().next().unwrap();

let semicolon_idx: usize = tokens.chars().position(|c| c == ';').unwrap();
/* LineBreak.txt list is ascii encoded so we can assume each char takes one byte: */
let chars_str: &str = &tokens[..semicolon_idx];

let mut codepoint_iter = chars_str.split("..");

let first_codepoint: u32 =
u32::from_str_radix(std::dbg!(codepoint_iter.next().unwrap()), 16).unwrap();

let sec_codepoint: u32 = codepoint_iter
.next()
.map(|v| u32::from_str_radix(std::dbg!(v), 16).unwrap())
.unwrap_or(first_codepoint);
let class = &tokens[semicolon_idx + 1..semicolon_idx + 1 + 2];
line_break_table.push((first_codepoint, sec_codepoint, LineBreakClass::from(class)));
}

let mut file = File::create(&mod_path)?;
file.write_all(b"use crate::types::LineBreakClass::*;\n")
.unwrap();
file.write_all(b"use crate::types::LineBreakClass;\n\n")
.unwrap();
file.write_all(b"const line_break_rules: &'static [(u32, u32, LineBreakClass)] = &[\n")
.unwrap();
for l in &line_break_table {
file.write_all(format!(" (0x{:X}, 0x{:X}, {:?}),\n", l.0, l.1, l.2).as_bytes())
.unwrap();
}
file.write_all(b"];").unwrap();
std::fs::remove_file(&tmpdir_path).unwrap();
tmpdir_path.pop();
std::fs::remove_dir(&tmpdir_path).unwrap();
Ok(())
}
134 changes: 134 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* bb - bin.rs
*
* Copyright 2019 Manos Pitsidianakis
*
* bb is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* bb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with bb. If not, see <http://www.gnu.org/licenses/>.
*/

//!
//! This crate contains the frontend stuff of the application. The application entry way on
//! `src/bin.rs` creates an event loop and passes input to the `ui` module.
//!
//! The mail handling stuff is done in the `bb` crate which includes all backend needs. The
//! split is done to theoretically be able to create different frontends with the same innards.
//!
extern crate crossbeam;
extern crate nix;
extern crate signal_hook;
extern crate termion;

use crossbeam::channel::{bounded, tick};
use crossbeam::select;
use libc::c_int;
use std::io::Error;
use std::time::{Duration, Instant};

mod ui;
use ui::*;

fn notify(signals: &[c_int]) -> Result<crossbeam::channel::Receiver<c_int>, Error> {
let (s, r) = bounded(100);
let signals = signal_hook::iterator::Signals::new(signals)?;
std::thread::spawn(move || {
for signal in signals.forever() {
s.send(signal).unwrap();
}
});
Ok(r)
}

fn main() -> Result<(), Error> {
let signals = &[
signal_hook::SIGALRM,
signal_hook::SIGTERM,
signal_hook::SIGINT,
signal_hook::SIGQUIT,
/* Catch SIGWINCH to handle terminal resizing */
signal_hook::SIGWINCH,
];

let ticker = tick(Duration::from_millis(800));

let signal_recvr = notify(signals)?;

/* Create the application State */
let mut state = State::new();

let receiver = state.receiver();

let window = Box::new(HSplit::new(
Box::new(ui::components::KernelMetrics::new()),
Box::new(ui::components::ProcessList::new()),
83,
false,
));

state.register_component(window);

/* Keep track of the input mode. See ui::UIMode for details */
'main: loop {
'inner: loop {
/* Poll on all channels. Currently we have the input channel for stdin, watching events and the signal watcher. */
select! {
recv(ticker) -> _ => {
state.redraw(true);
},
recv(signal_recvr) -> sig => {
eprintln!("got signal {:?}", sig);
match sig.unwrap() {
signal_hook::SIGWINCH => {
state.update_size();
state.render();
state.redraw(true);
},
_ => {}
}
},
recv(receiver) -> msg => {
match msg.unwrap() {
ThreadEvent::Input(Key::Ctrl('z')) => {
state.switch_to_main_screen();
//_thread_handler.join().expect("Couldn't join on the associated thread");
let self_pid = nix::unistd::Pid::this();
nix::sys::signal::kill(self_pid, nix::sys::signal::Signal::SIGSTOP).unwrap();
state.switch_to_alternate_screen();
state.restore_input();
// BUG: thread sends input event after one received key
state.update_size();
state.render();
state.redraw(true);
},
ThreadEvent::Input(k) => {
match k {
Key::Char('q') | Key::Char('Q') => {
drop(state);
break 'main;
},
key => {
state.rcv_event(UIEvent::Input(key));
state.redraw(false);
},
}
},
ThreadEvent::UIEvent(_) => {
},
}
},
}
} // end of 'inner
}
Ok(())
}
125 changes: 125 additions & 0 deletions src/ui.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* meli - ui crate.
*
* Copyright 2017-2018 Manos Pitsidianakis
*
* This file is part of meli.
*
* meli is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* meli is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/

/*!
* This library exports the public types and methods of its modules
*/

mod text_processing;
pub use crate::ui::text_processing::*;
#[macro_use]
mod types;
pub use crate::ui::types::*;

#[macro_use]
mod terminal;
pub use crate::ui::terminal::*;

pub mod state;
pub use crate::ui::state::*;

pub mod components;
pub use crate::ui::components::*;
pub use crate::ui::username::*;
pub mod username {
use libc;
use std::ptr::null_mut;
/* taken from whoami-0.1.1 */
fn getpwuid() -> libc::passwd {
let mut pwentp = null_mut();
let mut buffer = [0i8; 16384]; // from the man page
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "openbsd",
target_os = "netbsd"
))]
{
let mut pwent = libc::passwd {
pw_name: null_mut(),
pw_passwd: null_mut(),
pw_uid: 0,
pw_gid: 0,
pw_change: 0,
pw_class: null_mut(),
pw_gecos: null_mut(),
pw_dir: null_mut(),
pw_shell: null_mut(),
pw_expire: 0,
};
unsafe {
libc::getpwuid_r(
libc::geteuid(),
&mut pwent,
&mut buffer[0],
16384,
&mut pwentp,
);
}

pwent
}
#[cfg(target_os = "linux")]
{
let mut pwent = libc::passwd {
pw_name: null_mut(),
pw_passwd: null_mut(),
pw_uid: 0,
pw_gid: 0,
pw_gecos: null_mut(),
pw_dir: null_mut(),
pw_shell: null_mut(),
};

unsafe {
libc::getpwuid_r(
libc::geteuid(),
&mut pwent,
&mut buffer[0],
16384,
&mut pwentp,
);
}

pwent
}
}
fn ptr_to_string(name: *mut i8) -> String {
let uname = name as *mut _ as *mut u8;

let s;
let string;

unsafe {
s = ::std::slice::from_raw_parts(uname, libc::strlen(name));
string = String::from_utf8_lossy(s).to_string();
}

string
}
pub fn username() -> String {
let pwent = getpwuid();

ptr_to_string(pwent.pw_name)
}
}
Loading

0 comments on commit 31bf144

Please sign in to comment.