basic telnet support finally

pull/14/head
dvkt 4 years ago
parent 0989f94a85
commit 8cbd322cbf

@ -93,7 +93,6 @@ You can check whether TLS is enabled by visiting the About page:
## todo
- [ ] fork+exec telnet: gopher://bitreich.org/1/lawn/bbs
- [ ] ~/.config/phetch/phetch.conf
## bugs

@ -593,7 +593,6 @@ impl Menu {
)
}
Type::Error => Action::Error(line.name.to_string()),
Type::Telnet => Action::Error("Telnet support coming soon".into()),
t if !t.is_supported() => Action::Error(format!("{:?} not supported", t)),
_ => Action::Open(line.name.to_string(), url),
}

@ -13,13 +13,19 @@ use crate::{
};
use std::{
cell::RefCell,
io::{stdin, stdout, Result, Write},
io::{stdin, stdout, Result, Stdout, Write},
process::{self, Stdio},
sync::mpsc,
thread,
time::Duration,
};
use termion::{color, input::TermRead, raw::IntoRawMode, screen::AlternateScreen, terminal_size};
use termion::{
color,
input::TermRead,
raw::{IntoRawMode, RawTerminal},
screen::AlternateScreen,
terminal_size,
};
pub type Key = termion::event::Key;
pub type Page = Box<dyn View>;
@ -35,7 +41,7 @@ pub struct UI {
pub size: (usize, usize), // cols, rows
status: String, // status message, if any
tls: bool, // tls mode?
out: RefCell<Box<dyn Write>>,
out: RefCell<AlternateScreen<RawTerminal<Stdout>>>,
}
impl UI {
@ -45,6 +51,16 @@ impl UI {
size = (cols as usize, rows as usize);
};
// Store raw terminal but don't enable it yet or switch the
// screen. We don't want to stare at a fully blank screen
// while waiting for a slow page to load.
let out = AlternateScreen::from(
stdout()
.into_raw_mode()
.expect("Failed to initialize raw mode."),
);
out.suspend_raw_mode();
UI {
views: vec![],
focused: 0,
@ -53,16 +69,15 @@ impl UI {
size,
status: String::new(),
tls,
out: RefCell::new(Box::new(stdout())),
out: RefCell::new(out),
}
}
/// Prepare stdout for writing. Should be used in interactive
/// mode, eg inside run()
pub fn startup(&mut self) {
self.out = RefCell::new(Box::new(AlternateScreen::from(
stdout().into_raw_mode().unwrap(),
)));
let out = self.out.borrow_mut();
out.activate_raw_mode();
}
pub fn run(&mut self) -> Result<()> {
@ -120,6 +135,11 @@ impl UI {
}
}
// telnet
if url.starts_with("telnet://") {
return self.telnet(url);
}
// non-gopher URL
if url.contains("://") && !url.starts_with("gopher://") {
self.dirty = true;
@ -413,6 +433,23 @@ impl UI {
}
}
/// Opens an interactive telnet session.
fn telnet(&mut self, url: &str) -> Result<()> {
let (_, host, port, _) = gopher::parse_url(url);
let out = self.out.borrow_mut();
out.suspend_raw_mode();
let mut cmd = process::Command::new("telnet")
.arg(host)
.arg(port)
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.spawn()?;
cmd.wait();
out.activate_raw_mode();
self.dirty = true; // redraw when finished with session
Ok(())
}
fn process_page_input(&mut self) -> Action {
if let Some(page) = self.views.get_mut(self.focused) {
if let Ok(key) = stdin()

Loading…
Cancel
Save