fix clear screen

This commit is contained in:
Christien Rioux 2023-12-09 12:27:44 -05:00
parent 88d13d36c9
commit 8ed3f0672e
8 changed files with 196 additions and 77 deletions

42
Cargo.lock generated
View File

@ -242,12 +242,6 @@ dependencies = [
"password-hash",
]
[[package]]
name = "arraydeque"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0ffd3d69bd89910509a5d31d1f1353f38ccffdd116dd0099bbd6627f7bd8ad8"
[[package]]
name = "arrayref"
version = "0.3.7"
@ -1300,20 +1294,6 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "cursive-flexi-logger-view"
version = "0.5.0"
source = "git+https://gitlab.com/veilid/cursive-flexi-logger-view.git#7c931536b8c57339011bbe2ee604e431c91c0aa8"
dependencies = [
"arraydeque",
"cursive_core",
"flexi_logger",
"lazy_static",
"log",
"time",
"unicode-width",
]
[[package]]
name = "cursive-macros"
version = "0.1.0"
@ -2233,6 +2213,15 @@ dependencies = [
"ahash 0.7.7",
]
[[package]]
name = "hashbrown"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
dependencies = [
"ahash 0.8.6",
]
[[package]]
name = "hashbrown"
version = "0.14.2"
@ -2835,6 +2824,15 @@ dependencies = [
"value-bag",
]
[[package]]
name = "lru"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670"
dependencies = [
"hashbrown 0.13.2",
]
[[package]]
name = "lru-cache"
version = "0.1.2"
@ -5491,7 +5489,6 @@ dependencies = [
"config",
"crossbeam-channel",
"cursive",
"cursive-flexi-logger-view",
"cursive_buffered_backend",
"cursive_table_view",
"data-encoding",
@ -5503,6 +5500,8 @@ dependencies = [
"indent",
"json",
"log",
"lru",
"owning_ref",
"parking_lot 0.12.1",
"serde",
"serde_derive",
@ -5511,6 +5510,7 @@ dependencies = [
"thiserror",
"tokio",
"tokio-util",
"unicode-width",
"veilid-bugsalot",
"veilid-tools",
]

View File

@ -34,7 +34,7 @@ cursive = { git = "https://gitlab.com/veilid/cursive.git", default-features = fa
"toml",
"ansi",
] }
cursive-flexi-logger-view = { git = "https://gitlab.com/veilid/cursive-flexi-logger-view.git" }
cursive_buffered_backend = { git = "https://gitlab.com/veilid/cursive-buffered-backend.git" }
# cursive-multiplex = "0.6.0"
# cursive_tree_view = "0.6.0"
@ -64,6 +64,9 @@ data-encoding = { version = "^2" }
indent = { version = "0.1.1" }
chrono = "0.4.26"
owning_ref = "0.4.1"
unicode-width = "0.1.10"
lru = "0.10.0"
[dev-dependencies]
serial_test = "^2"

View File

@ -189,7 +189,7 @@ Server Debug Commands:
ui.send_callback(callback);
}
Err(e) => {
ui.add_node_event(Level::Error, e.to_string());
ui.add_node_event(Level::Error, format!("{}\n", e));
ui.send_callback(callback);
}
}
@ -424,7 +424,7 @@ Server Debug Commands:
self.inner().ui_sender.add_node_event(
log_level,
format!(
"{}: {}{}",
"{}: {}{}\n",
log["log_level"].as_str().unwrap_or("???"),
log["message"].as_str().unwrap_or("???"),
if let Some(bt) = log["backtrace"].as_str() {
@ -466,7 +466,7 @@ Server Debug Commands:
self.inner().ui_sender.add_node_event(
Level::Info,
format!(
"AppMessage ({:?}): {}{}",
"AppMessage ({:?}): {}{}\n",
msg["sender"],
strmsg,
if truncated { "..." } else { "" }
@ -506,7 +506,7 @@ Server Debug Commands:
self.inner().ui_sender.add_node_event(
Level::Info,
format!(
"AppCall ({:?}) id = {:016x} : {}{}",
"AppCall ({:?}) id = {:016x} : {}{}\n",
call["sender"],
id,
strmsg,

View File

@ -9,6 +9,7 @@ use clap::{Parser, ValueEnum};
use flexi_logger::*;
use std::{net::ToSocketAddrs, path::PathBuf};
mod cached_text_view;
mod client_api_connection;
mod command_processor;
mod peers_table_view;
@ -91,7 +92,6 @@ fn main() -> Result<(), String> {
let logger = Logger::with(specbuilder.build());
if settings.logging.terminal.enabled {
let flv = sivui.cursive_flexi_logger();
if settings.logging.file.enabled {
std::fs::create_dir_all(settings.logging.file.directory.clone())
.map_err(map_to_string)?;
@ -100,13 +100,13 @@ fn main() -> Result<(), String> {
FileSpec::default()
.directory(settings.logging.file.directory.clone())
.suppress_timestamp(),
flv,
Box::new(uisender.clone()),
)
.start()
.expect("failed to initialize logger!");
} else {
logger
.log_to_writer(flv)
.log_to_writer(Box::new(uisender.clone()))
.start()
.expect("failed to initialize logger!");
}

View File

@ -7,13 +7,16 @@ use cursive::align::*;
use cursive::event::*;
use cursive::theme::*;
use cursive::traits::*;
use cursive::utils::markup::ansi;
use cursive::utils::markup::StyledString;
use cursive::view::SizeConstraint;
use cursive::views::*;
use cursive::Cursive;
use cursive::CursiveRunnable;
use cursive_flexi_logger_view::{CursiveLogWriter, FlexiLoggerView};
use flexi_logger::writers::LogWriter;
use flexi_logger::DeferredNow;
// use cursive_multiplex::*;
use crate::cached_text_view::*;
use chrono::{Datelike, Timelike};
use std::collections::{HashMap, VecDeque};
use std::io::Write;
@ -50,6 +53,7 @@ impl<T> Dirty<T> {
}
pub type UICallback = Box<dyn Fn(&mut Cursive) + Send>;
pub type NodeEventsPanel = Panel<NamedView<ScrollView<NamedView<CachedTextView>>>>;
static START_TIME: AtomicU64 = AtomicU64::new(0);
@ -219,12 +223,25 @@ impl UI {
});
}
fn clear_handler(siv: &mut Cursive) {
cursive_flexi_logger_view::clear_log();
Self::node_events_view(siv).set_content("");
UI::update_cb(siv);
}
fn node_events_panel(s: &mut Cursive) -> ViewRef<Panel<ScrollView<FlexiLoggerView>>> {
////////////////////////////////////////////////////////////////////////////////////////////////
// Selectors
// fn main_layout(s: &mut Cursive) -> ViewRef<LinearLayout> {
// s.find_name("main-layout").unwrap()
// }
fn node_events_panel(s: &mut Cursive) -> ViewRef<NodeEventsPanel> {
s.find_name("node-events-panel").unwrap()
}
fn node_events_view(s: &mut Cursive) -> ViewRef<CachedTextView> {
s.find_name("node-events-view").unwrap()
}
// fn node_events_scroll_view(s: &mut Cursive) -> ViewRef<ScrollView<CachedTextView>> {
// s.find_name("node-events-scroll-view").unwrap()
// }
fn command_line(s: &mut Cursive) -> ViewRef<EditView> {
s.find_name("command-line").unwrap()
}
@ -237,6 +254,27 @@ impl UI {
fn peers(s: &mut Cursive) -> ViewRef<PeersTableView> {
s.find_name("peers").unwrap()
}
fn connection_address(s: &mut Cursive) -> ViewRef<EditView> {
s.find_name("connection-address").unwrap()
}
fn connection_dialog(s: &mut Cursive) -> ViewRef<Dialog> {
s.find_name("connection-dialog").unwrap()
}
////////////////////////////////////////////////////////////////////////////////////////////////
pub fn push_styled(s: &mut Cursive, styled_string: StyledString) {
let mut ctv = UI::node_events_view(s);
ctv.append(styled_string)
}
pub fn push_ansi_lines(s: &mut Cursive, starting_style: Style, lines: String) {
let mut ctv = UI::node_events_view(s);
let (spanned_string, _end_style) = ansi::parse_with_starting_style(starting_style, lines);
ctv.append(spanned_string);
}
////////////////////////////////////////////////////////////////////////////////////////////////
fn render_attachment_state(inner: &mut UIInner) -> String {
let att = match inner.ui_state.attachment_state.get().as_str() {
"Detached" => "[----]",
@ -351,16 +389,17 @@ impl UI {
return;
}
// run command
cursive_flexi_logger_view::parse_lines_to_log(
UI::push_ansi_lines(
s,
ColorStyle::primary().into(),
format!("> {} {}", UI::cli_ts(Self::get_start_time()), text),
format!("{}> {}\n", UI::cli_ts(Self::get_start_time()), text),
);
match Self::run_command(s, text) {
Ok(_) => {}
Err(e) => {
let color = *Self::inner_mut(s).log_colors.get(&Level::Error).unwrap();
cursive_flexi_logger_view::parse_lines_to_log(
UI::push_ansi_lines(
s,
color.into(),
format!(" {} Error: {}", UI::cli_ts(Self::get_start_time()), e),
);
@ -446,7 +485,7 @@ impl UI {
}
fn submit_connection_address(s: &mut Cursive) {
let edit = s.find_name::<EditView>("connection-address").unwrap();
let edit = Self::connection_address(s);
let addr = (*edit.get_content()).clone();
let sa = match addr.parse::<std::net::SocketAddr>() {
Ok(sa) => Some(sa),
@ -475,7 +514,8 @@ impl UI {
&& std::io::stdout().flush().is_ok()
{
let color = *Self::inner_mut(s).log_colors.get(&Level::Info).unwrap();
cursive_flexi_logger_view::parse_lines_to_log(
UI::push_ansi_lines(
s,
color.into(),
format!(
">> {} Copied: {}",
@ -491,7 +531,8 @@ impl UI {
// X11/Wayland/other system copy
if clipboard.set_text(text.as_ref()).is_ok() {
let color = *Self::inner_mut(s).log_colors.get(&Level::Info).unwrap();
cursive_flexi_logger_view::parse_lines_to_log(
UI::push_ansi_lines(
s,
color.into(),
format!(
">> {} Copied: {}",
@ -501,7 +542,8 @@ impl UI {
);
} else {
let color = *Self::inner_mut(s).log_colors.get(&Level::Warn).unwrap();
cursive_flexi_logger_view::parse_lines_to_log(
UI::push_ansi_lines(
s,
color.into(),
format!(
">> {} Could not copy to clipboard",
@ -622,7 +664,7 @@ impl UI {
return true;
}
if reset {
let mut dlg = s.find_name::<Dialog>("connection-dialog").unwrap();
let mut dlg = Self::connection_dialog(s);
dlg.clear_buttons();
return true;
}
@ -644,20 +686,20 @@ impl UI {
Some(addr) => addr.to_string(),
};
debug!("address is {}", addr);
let mut edit = s.find_name::<EditView>("connection-address").unwrap();
let mut edit = Self::connection_address(s);
edit.set_content(addr);
edit.set_enabled(true);
let mut dlg = s.find_name::<Dialog>("connection-dialog").unwrap();
let mut dlg = Self::connection_dialog(s);
dlg.add_button("Connect", Self::submit_connection_address);
}
ConnectionState::Connected(_, _) => {}
ConnectionState::Retrying(addr, _) => {
//
let mut edit = s.find_name::<EditView>("connection-address").unwrap();
let mut edit = Self::connection_address(s);
debug!("address is {}", addr);
edit.set_content(addr.to_string());
edit.set_enabled(false);
let mut dlg = s.find_name::<Dialog>("connection-dialog").unwrap();
let mut dlg = Self::connection_dialog(s);
dlg.add_button("Cancel", |s| {
Self::command_processor(s).cancel_reconnect();
});
@ -837,9 +879,23 @@ impl UI {
START_TIME.load(Ordering::Relaxed)
}
pub fn new(node_log_scrollback: usize, settings: &Settings) -> (Self, UISender) {
cursive_flexi_logger_view::resize(node_log_scrollback);
fn make_node_events_panel(
node_log_scrollback: usize,
) -> ResizedView<NamedView<NodeEventsPanel>> {
Panel::new(
CachedTextView::new("", node_log_scrollback)
.with_name("node-events-view")
.scrollable()
.scroll_strategy(cursive::view::ScrollStrategy::StickToBottom)
.with_name("node-events-scroll-view"),
)
.title_position(HAlign::Left)
.title("Node Events")
.with_name("node-events-panel")
.full_screen()
}
pub fn new(node_log_scrollback: usize, settings: &Settings) -> (Self, UISender) {
UI::set_start_time();
// Instantiate the cursive runnable
let runnable = CursiveRunnable::new(
@ -874,6 +930,7 @@ impl UI {
let ui_sender = UISender {
inner: this.inner.clone(),
cb_sink,
colors: default_log_colors(),
};
let mut inner = this.inner.lock();
@ -882,13 +939,7 @@ impl UI {
this.siv.set_user_data(this.inner.clone());
// Create layouts
let node_events_view = Panel::new(FlexiLoggerView::new_scrollable())
.title_position(HAlign::Left)
.title("Node Events")
.with_name("node-events-panel")
.full_screen();
let node_events_view = Self::make_node_events_panel(node_log_scrollback);
let mut peers_table_view = PeersTableView::new()
.column(PeerTableColumn::NodeId, "Node Id", |c| c.width(48))
.column(PeerTableColumn::Address, "Address", |c| c)
@ -967,7 +1018,8 @@ impl UI {
.child(TextView::new(version)),
);
this.siv.add_fullscreen_layer(mainlayout);
this.siv
.add_fullscreen_layer(mainlayout.with_name("main-layout"));
UI::setup_colors(&mut this.siv, &mut inner, settings);
UI::setup_quit_handler(&mut this.siv);
@ -978,11 +1030,7 @@ impl UI {
(this, ui_sender)
}
pub fn cursive_flexi_logger(&self) -> Box<CursiveLogWriter> {
let mut flv = cursive_flexi_logger_view::cursive_flexi_logger(self.siv.cb_sink().clone());
flv.set_colors(self.inner.lock().log_colors.clone());
flv
}
pub fn set_command_processor(&mut self, cmdproc: CommandProcessor) {
let mut inner = self.inner.lock();
inner.cmdproc = Some(cmdproc);
@ -999,10 +1047,22 @@ impl UI {
type CallbackSink = Box<dyn FnOnce(&mut Cursive) + 'static + Send>;
/// Default log colors
fn default_log_colors() -> HashMap<Level, Color> {
let mut colors = HashMap::<Level, Color>::new();
colors.insert(Level::Trace, Color::Dark(BaseColor::Green));
colors.insert(Level::Debug, Color::Dark(BaseColor::Cyan));
colors.insert(Level::Info, Color::Dark(BaseColor::Blue));
colors.insert(Level::Warn, Color::Dark(BaseColor::Yellow));
colors.insert(Level::Error, Color::Dark(BaseColor::Red));
colors
}
#[derive(Clone)]
pub struct UISender {
inner: Arc<Mutex<UIInner>>,
cb_sink: Sender<CallbackSink>,
colors: HashMap<Level, Color>,
}
impl UISender {
@ -1094,14 +1154,71 @@ impl UISender {
}
pub fn add_node_event(&self, log_color: Level, event: String) {
{
let color = {
let inner = self.inner.lock();
let color = *inner.log_colors.get(&log_color).unwrap();
cursive_flexi_logger_view::parse_lines_to_log(
*inner.log_colors.get(&log_color).unwrap()
};
let _ = self.push_styled_lines(
color.into(),
format!("{}: {}", UI::cli_ts(UI::get_start_time()), event),
format!("{}: {}\n", UI::cli_ts(UI::get_start_time()), event),
);
}
let _ = self.cb_sink.send(Box::new(UI::update_cb));
pub fn push_styled(&self, styled_string: StyledString) -> std::io::Result<()> {
let res = self.cb_sink.send(Box::new(move |s| {
UI::push_styled(s, styled_string);
}));
if res.is_err() {
return Err(std::io::Error::from(std::io::ErrorKind::BrokenPipe));
}
Ok(())
}
pub fn push_styled_lines(&self, starting_style: Style, lines: String) -> std::io::Result<()> {
let res = self.cb_sink.send(Box::new(move |s| {
UI::push_ansi_lines(s, starting_style, lines);
}));
if res.is_err() {
return Err(std::io::Error::from(std::io::ErrorKind::BrokenPipe));
}
Ok(())
}
}
impl LogWriter for UISender {
fn write(&self, _now: &mut DeferredNow, record: &Record) -> std::io::Result<()> {
let color = *self.colors.get(&record.level()).unwrap();
let args = format!("{}", &record.args());
let mut line = StyledString::new();
let mut indent = 0;
let levstr = format!("{}: ", record.level());
indent += levstr.len();
line.append_styled(levstr, color);
let filestr = format!(
"{}:{} ",
record.file().unwrap_or("(unnamed)"),
record.line().unwrap_or(0),
);
indent += filestr.len();
line.append_plain(filestr);
for argline in args.lines() {
line.append_styled(argline, color);
self.push_styled(line)?;
line = StyledString::new();
line.append_plain(" ".repeat(indent));
}
Ok(())
}
fn flush(&self) -> std::io::Result<()> {
// we are not buffering
Ok(())
}
fn max_log_level(&self) -> log::LevelFilter {
log::LevelFilter::max()
}
}

View File

@ -401,7 +401,7 @@ impl IGDManager {
let desc = this.get_description(k.llpt, k.local_port);
match gw.add_port(convert_llpt(k.llpt), v.mapped_port, SocketAddr::new(local_ip, k.local_port), (UPNP_MAPPING_LIFETIME_MS + 999) / 1000, &desc) {
Ok(()) => {
log_net!(debug "renewed mapped port {:?} -> {:?}", v, k);
log_net!("renewed mapped port {:?} -> {:?}", v, k);
inner.port_maps.insert(k, PortMapValue {
ext_ip: v.ext_ip,

View File

@ -1499,8 +1499,7 @@ impl VeilidAPI {
let mut dc = DEBUG_CACHE.lock();
dc.opened_record_contexts.insert(*record.key(), rc);
debug!("DHT Record Opened:\n{:#?}", record);
Ok(format!("Opened: {:?}", record))
Ok(format!("Opened: {} : {:?}", key, record))
}
async fn debug_record_close(&self, args: Vec<String>) -> VeilidAPIResult<String> {
@ -1511,7 +1510,6 @@ impl VeilidAPI {
return Ok(format!("Can't close DHT record: {}", e));
};
debug!("DHT Record Closed:\n{:#?}", key);
Ok(format!("Closed: {:?}", key))
}
@ -1648,7 +1646,7 @@ impl VeilidAPI {
Ok(v) => v,
};
Ok(format!("Expiration at: {:?}", debug_ts(ts.as_u64())))
Ok(format!("Success: expiration={:?}", debug_ts(ts.as_u64())))
}
async fn debug_record_cancel(&self, args: Vec<String>) -> VeilidAPIResult<String> {
@ -1665,10 +1663,11 @@ impl VeilidAPI {
Ok(v) => v,
};
Ok(format!(
"Still Active: {:?}",
if still_active { "true" } else { "false" }
))
Ok(if still_active {
"Watch partially cancelled".to_owned()
} else {
"Watch cancelled".to_owned()
})
}
async fn debug_record(&self, args: String) -> VeilidAPIResult<String> {

View File

@ -485,7 +485,7 @@ impl PlatformSupportApple {
) {
Ok(v) => v,
Err(e) => {
log_net!(error "failed to get address flags: {}", e);
log_net!(debug "failed to get address flags for ifname={}, ifaddr={:?} : {}", ifname, ifaddr.ifa_addr, e);
continue;
}
};