Skip to content

Commit

Permalink
added notifications and file/history completion
Browse files Browse the repository at this point in the history
Signed-off-by: wadeking98 <[email protected]>
  • Loading branch information
wadeking98 committed Oct 25, 2023
1 parent 74bb0a3 commit cec217f
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 45 deletions.
84 changes: 80 additions & 4 deletions src/input/input.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
use std::{io::stdin, sync::Arc};
use std::{
io::{stdin, stdout, Write},
sync::Arc,
};

use rustyline::{
completion::{Completer, FilenameCompleter, Pair},
highlight::Highlighter,
hint::{Hinter, HistoryHinter},
history::History,
Editor,
validate::Validator,
Editor, Helper,
};
use termion::{
clear, color, cursor,
event::{Event, Key},
input::TermReadEventsAndRaw,
};
Expand All @@ -16,12 +24,80 @@ use tokio::{
task,
};

pub async fn read_line<H>(
rl: Arc<Mutex<Editor<(), H>>>,
pub struct CompletionHelper {
completer: Option<FilenameCompleter>,
hinter: HistoryHinter,
}
impl Helper for CompletionHelper {}
impl Hinter for CompletionHelper {
type Hint = String;
fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<Self::Hint> {
return self.hinter.hint(line, pos, ctx);
}
}
impl Highlighter for CompletionHelper {}
impl Validator for CompletionHelper {}
impl Completer for CompletionHelper {
type Candidate = Pair;
fn complete(
&self, // FIXME should be `&mut self`
line: &str,
pos: usize,
ctx: &rustyline::Context<'_>,
) -> rustyline::Result<(usize, Vec<Self::Candidate>)> {
return match &self.completer {
Some(completer) => completer.complete(line, pos, ctx),
None => Ok((0, Vec::new())),
};
}
}

impl CompletionHelper {
pub fn new() -> CompletionHelper {
let helper: CompletionHelper = CompletionHelper {
completer: Some(FilenameCompleter::new()),
hinter: HistoryHinter {},
};
return helper;
}
pub fn new_only_hinter() -> CompletionHelper {
let helper: CompletionHelper = CompletionHelper {
completer: None,
hinter: HistoryHinter {},
};
return helper;
}
}

pub fn display_notification(text: String) {
let mut stdout = stdout();
let notification = format!(
"{goto}{clear}{success}{text}{reset}",
goto = cursor::Goto(1, 1),
clear = clear::CurrentLine,
success = color::Fg(color::LightGreen),
reset = color::Fg(color::Reset),
);

// save cursor position
write!(stdout, "{}", cursor::Save).unwrap();
stdout.flush().unwrap();

stdout.write_all(&notification.as_bytes()).unwrap();
stdout.flush().unwrap();

// restore cursor position
write!(stdout, "{}", cursor::Restore).unwrap();
stdout.flush().unwrap();
}

pub async fn read_line<T, H>(
rl: Arc<Mutex<Editor<T, H>>>,
prompt: Option<&str>,
) -> Result<String, RecvError>
where
H: History + Send + 'static,
T: Helper + Send + 'static,
{
let (tx, rx) = oneshot::channel::<String>();
let input_prompt = match prompt {
Expand Down
56 changes: 20 additions & 36 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@ use std::collections::HashMap;
use std::env::{self, set_current_dir};
use std::sync::Arc;

use input::input::read_line;
use input::input::{read_line, CompletionHelper};
use menu::menu_list::clear;
use rustyline::DefaultEditor;
use rustyline::history::MemHistory;
use rustyline::{Config, CompletionType, Editor};
use std::process::{exit, Command};
use termion::raw::IntoRawMode;

use crate::input::input::display_notification;
use crate::menu::menu_list;
use crate::socket::{connection, listener};
use connection::{handle_new_shell, Handle};
use futures_util::pin_mut;
use futures_util::stream::StreamExt;
use std::io::{stdout, Write};
use termion::{self, clear, color, cursor};
use std::io::stdout;
use termion::{self, color};
use tokio::sync::Mutex;

mod input;
Expand Down Expand Up @@ -45,7 +47,14 @@ fn input_loop(
init_message: Option<String>,
) {
tokio::spawn(async move {
let menu_rl = Arc::new(Mutex::new(DefaultEditor::new().unwrap()));
let history = MemHistory::new();
let mut builder = Config::builder();
builder = builder.completion_type(CompletionType::Circular);
let config = builder.build();
let mut rl = Editor::with_history(config, history).unwrap();
let helper = CompletionHelper::new();
rl.set_helper(Some(helper));
let menu_rl = Arc::new(Mutex::new(rl));
clear();
if init_message.is_some() {
let msg = init_message.unwrap();
Expand Down Expand Up @@ -144,37 +153,12 @@ async fn main() {
exit(1)
}
};
// display notification, I know this is gross but it's the best I can do with rustyline getting in the way :(
let mut stdout = stdout();
let notification = format!(
"{goto}{clear}{success}new shell received from {addr} !{reset}",
goto = cursor::Goto(1, 1),
clear = clear::CurrentLine,
success = color::Fg(color::LightGreen),
addr = soc.peer_addr().unwrap().to_string(),
reset = color::Fg(color::Reset),
);
// save cursor position
stdout
.write_all(&"\x1B7".as_bytes())
.unwrap();
stdout.flush().unwrap();

stdout
.write_all(
&notification
.as_bytes(),
)
.unwrap();
stdout.flush().unwrap();

// restore cursor position
stdout
.write_all(&"\x1B8".as_bytes())
.unwrap();
stdout.flush().unwrap();

handle_new_shell(soc, connected_shells.clone(), None).await;

let soc_added = handle_new_shell(soc, connected_shells.clone(), None).await;

if soc_added {
display_notification(String::from("new shell received!"));
}
}
}

Expand Down
15 changes: 10 additions & 5 deletions src/socket/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ use tokio::net::TcpStream;
use tokio::sync::Mutex;
use tokio::time::sleep;

use crate::input::input::CompletionHelper;

#[derive(Clone)]
pub struct Handle {
pub readline: Arc<Mutex<Editor<(), MemHistory>>>,
pub readline: Arc<Mutex<Editor<CompletionHelper, MemHistory>>>,
pub read_stream: Arc<Mutex<OwnedReadHalf>>,
pub write_stream: Arc<Mutex<OwnedWriteHalf>>,
pub raw_mode: bool,
Expand All @@ -25,8 +27,10 @@ impl Handle {
let mut builder = Config::builder();
builder = builder.check_cursor_position(false);
let config = builder.build();
let mut rl = Editor::with_history(config, history).unwrap();
rl.set_helper(Some(CompletionHelper::new_only_hinter()));
let handle = Handle {
readline: Arc::new(Mutex::new(Editor::with_history(config, history).unwrap())),
readline: Arc::new(Mutex::new(rl)),
read_stream: Arc::new(Mutex::new(read_stream)),
write_stream: Arc::new(Mutex::new(write_stream)),
raw_mode: false,
Expand Down Expand Up @@ -66,7 +70,7 @@ pub async fn handle_new_shell(
soc: TcpStream,
connected_shells: Arc<Mutex<HashMap<String, Handle>>>,
skip_validation: Option<bool>,
) {
) -> bool {
let soc_addr = soc.peer_addr();
let (soc_read, soc_write) = soc.into_split();
let handle = Handle::new(soc_read, soc_write);
Expand All @@ -90,11 +94,12 @@ pub async fn handle_new_shell(
let mut shells = connected_shells.lock().await;
shells.insert(soc_key, handle);
} else {
return;
return false;
}
}
Err(_) => return,
Err(_) => return false,
}
return true;
}

#[cfg(test)]
Expand Down

0 comments on commit cec217f

Please sign in to comment.