share config so we can modify it in views

pull/22/head
chris west 4 years ago
parent c07656509f
commit cf9e16650e

@ -43,7 +43,7 @@ impl Error for ArgError {
pub fn parse<T: AsRef<str>>(args: &[T]) -> Result<Config, ArgError> {
let mut set_nocfg = false;
let mut set_cfg = false;
let mut cfg = config::default();
let mut cfg = Config::default();
// check for config to load / not load first
let mut iter = args.iter();
@ -61,12 +61,8 @@ pub fn parse<T: AsRef<str>>(args: &[T]) -> Result<Config, ArgError> {
}
set_cfg = true;
if let Some(arg) = iter.next() {
cfg = match config::load_file(arg.as_ref()) {
Ok(c) => c,
Err(e) => {
return Err(ArgError::new(format!("error loading config: {}", e)));
}
};
cfg = config::load_file(arg.as_ref())
.map_err(|e| ArgError::new(format!("error loading config: {}", e)))?;
} else {
return Err(ArgError::new("need a config file"));
}

@ -9,9 +9,13 @@ use {
collections::HashMap,
fs::OpenOptions,
io::{Read, Result},
sync::{Arc, RwLock},
},
};
/// Global, shared config.
pub type SharedConfig = Arc<RwLock<Config>>;
/// phetch will look for this file on load.
const CONFIG_FILE: &str = "phetch.conf";
@ -113,8 +117,8 @@ pub fn exists() -> bool {
}
/// Parses a phetch config file into a Config struct.
pub fn parse(text: &str) -> Result<Config> {
let mut cfg = default();
fn parse(text: &str) -> Result<Config> {
let mut cfg = Config::default();
let mut keys: HashMap<&str, bool> = HashMap::new();
for (mut linenum, line) in text.split_terminator('\n').enumerate() {
@ -154,9 +158,8 @@ pub fn parse(text: &str) -> Result<Config> {
}
}
"encoding" => {
cfg.encoding = Encoding::from_str(val).map_err(|e|{
error!("{} on line {}: {:?}",e, linenum, line)
})?;
cfg.encoding = Encoding::from_str(val)
.map_err(|e| error!("{} on line {}: {:?}", e, linenum, line))?;
}
_ => return Err(error!("Unknown key on line {}: {}", linenum, key)),
}

@ -7,7 +7,7 @@
//! it returns an Action to the UI representing its intent.
use crate::{
config::Config,
config::SharedConfig as Config,
gopher::{self, Type},
terminal,
ui::{self, Action, Key, View, MAX_COLS, SCROLL_LINES},
@ -249,12 +249,12 @@ impl View for Menu {
impl Menu {
/// Create a representation of a Gopher Menu from a raw Gopher
/// response and a few options.
pub fn from(url: &str, response: String, config: &Config, tls: bool) -> Menu {
pub fn from(url: &str, response: String, config: Config, tls: bool) -> Menu {
Menu {
tls,
tor: config.tor,
wide: config.wide,
mode: config.mode,
tor: config.read().unwrap().tor,
wide: config.read().unwrap().wide,
mode: config.read().unwrap().mode,
..parse(url, response)
}
}

@ -178,7 +178,7 @@ impl View for Text {
impl Text {
/// Create a Text View from a raw Gopher response and a few options.
pub fn from(url: &str, response: Vec<u8>, config: &Config, tls: bool) -> Text {
pub fn from(url: &str, response: Vec<u8>, config: Config, tls: bool) -> Text {
let mut lines = 0;
let mut longest = 0;
let mut line_len = 0;
@ -194,18 +194,24 @@ impl Text {
}
}
let mode = config.read().unwrap().mode;
let tor = config.read().unwrap().tor;
let encoding = config.read().unwrap().encoding;
let wide = config.read().unwrap().wide;
Text {
config,
url: url.into(),
raw_response: response,
scroll: 0,
lines,
longest,
size: (0, 0),
mode: config.mode,
mode,
tls,
tor: config.tor,
encoding: config.encoding,
wide: config.wide,
tor,
encoding,
wide,
}
}
@ -250,7 +256,7 @@ mod test {
#[test]
fn test_cp437() {
let body = include_bytes!("../tests/CP437.txt");
let mut text = Text::from("", body.to_vec(), &Config::default(), false);
let mut text = Text::from("", body.to_vec(), Config::default(), false);
text.mode = ui::Mode::Print;
let res = text.render();

@ -18,7 +18,7 @@ pub use self::{action::Action, mode::Mode, view::View};
use crate::{
bookmarks, color,
config::Config,
config::{Config, SharedConfig},
encoding::Encoding,
gopher::{self, Type},
help, history,
@ -32,7 +32,7 @@ use std::{
process::{self, Stdio},
sync::{
mpsc::{channel, Receiver, Sender},
Arc, Mutex,
Arc, Mutex, RwLock,
},
thread,
time::Duration,
@ -92,7 +92,7 @@ pub struct UI {
/// Status message to display on screen, if any
status: String,
/// User config. Command line options + phetch.conf
config: Config,
config: SharedConfig,
/// Channel where UI events are sent.
keys: KeyReceiver,
}
@ -111,7 +111,7 @@ impl UI {
dirty: true,
running: true,
size,
config,
config: Arc::new(RwLock::new(config)),
status: String::new(),
keys: Self::spawn_keyboard_listener(),
}
@ -204,10 +204,10 @@ impl UI {
// binary downloads
let typ = gopher::type_for_url(url);
if typ.is_media() && self.config.media.is_some() {
if typ.is_media() && self.config.read().unwrap().media.is_some() {
self.dirty = true;
return if self.confirm(&format!("Open in media player? {}", url)) {
utils::open_media(self.config.media.as_ref().unwrap(), url)
utils::open_media(self.config.read().unwrap().media.as_ref().unwrap(), url)
} else {
Ok(())
};
@ -230,7 +230,10 @@ impl UI {
/// Download a binary file. Used by `open()` internally.
fn download(&mut self, url: &str) -> Result<()> {
let url = url.to_string();
let (tls, tor) = (self.config.tls, self.config.tor);
let (tls, tor) = (
self.config.read().unwrap().tls,
self.config.read().unwrap().tor,
);
let chan = self.keys.clone();
self.spinner(&format!("Downloading {}", url), move || {
gopher::download_url(&url, tls, tor, chan)
@ -260,7 +263,10 @@ impl UI {
thread::spawn(move || history::save(&hname, &hurl));
// request thread
let thread_url = url.to_string();
let (tls, tor) = (self.config.tls, self.config.tor);
let (tls, tor) = (
self.config.read().unwrap().tls,
self.config.read().unwrap().tor,
);
// don't spin on first ever request
let (tls, res) = if self.views.is_empty() {
gopher::fetch_url(&thread_url, tls, tor)?
@ -272,10 +278,10 @@ impl UI {
Type::Menu | Type::Search => Ok(Box::new(Menu::from(
url,
gopher::response_to_string(&res),
&self.config,
self.config.clone(),
tls,
))),
Type::Text | Type::HTML => Ok(Box::new(Text::from(url, res, &self.config, tls))),
Type::Text | Type::HTML => Ok(Box::new(Text::from(url, res, self.config.clone(), tls))),
_ => Err(error!("Unsupported Gopher Response: {:?}", typ)),
}
}
@ -286,7 +292,12 @@ impl UI {
&url.trim_start_matches("gopher://phetch/")
.trim_start_matches("1/"),
) {
Ok(Box::new(Menu::from(url, source, &self.config, false)))
Ok(Box::new(Menu::from(
url,
source,
self.config.clone(),
false,
)))
} else {
Err(error!("phetch URL not found: {}", url))
}
@ -383,13 +394,13 @@ impl UI {
}
if view.is_tls() {
if self.config.emoji {
if self.config.read().unwrap().emoji {
status.push("🔐");
} else {
status.push("TLS");
}
} else if view.is_tor() {
if self.config.emoji {
if self.config.read().unwrap().emoji {
status.push("🧅");
} else {
status.push("TOR");
@ -653,7 +664,7 @@ impl UI {
if let Some(view) = self.views.get(self.focused) {
let url = view.url();
let mut text =
Text::from(url, view.raw().into(), &self.config, view.is_tls());
Text::from(url, view.raw().into(), self.config.clone(), view.is_tls());
text.wide = true;
self.add_view(Box::new(text));
}
@ -687,7 +698,8 @@ impl UI {
}
}
'w' => {
self.config.wide = !self.config.wide;
let wide = self.config.read().unwrap().wide;
self.config.write().unwrap().wide = !wide;
if let Some(view) = self.views.get_mut(self.focused) {
let w = view.wide();
view.set_wide(!w);

Loading…
Cancel
Save