From c873e4250c58d872763129bff2c0b0e6c91c0a2a Mon Sep 17 00:00:00 2001 From: Eskil Queseth Date: Sat, 17 Oct 2020 18:39:36 +0200 Subject: add pretty printing for mumctl status --- mumctl/src/main.rs | 19 +++++++++-- mumd/src/state.rs | 2 +- mumlib/src/state.rs | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 4 deletions(-) diff --git a/mumctl/src/main.rs b/mumctl/src/main.rs index cfd48f8..c73b793 100644 --- a/mumctl/src/main.rs +++ b/mumctl/src/main.rs @@ -6,6 +6,8 @@ use std::{fs, io, iter}; use colored::Colorize; use mumlib::state::Channel; +const INDENTATION: &str = " "; + macro_rules! err_print { ($func:expr) => { if let Err(e) = $func { @@ -84,7 +86,18 @@ fn main() { } else if let Some(_matches) = matches.subcommand_matches("status") { match send_command(Command::Status) { Ok(res) => { - println!("{:#?}", res.unwrap()); + match res { + Some(CommandResponse::Status { server_state }) => { + println!("Connected to {} as {}", server_state.host, server_state.username); + let own_channel = server_state.channels.iter().find(|e| e.users.iter().any(|e| e.name == server_state.username)).unwrap(); + println!("Currently in {} with {} other client{}:", own_channel.name, own_channel.users.len() - 1, if own_channel.users.len() == 2 { "" } else { "s" }); + println!("{}{}", INDENTATION, own_channel.name); + for user in &own_channel.users { + println!("{}{}{}", INDENTATION, INDENTATION, user); + } + } + _ => unreachable!(), + } } Err(e) => println!("{} {}", "error:".red(), e), } @@ -119,13 +132,13 @@ fn send_command(command: Command) -> mumlib::error::Result(), channel.name.bold(), if channel.max_users != 0 { + println!("{}{}{}", iter::repeat(INDENTATION).take(depth).collect::(), channel.name.bold(), if channel.max_users != 0 { format!(" {}/{}", channel.users.len(), channel.max_users) } else { "".to_string() }); for user in &channel.users { - println!("{}-{}", iter::repeat(" ").take(depth + 1).collect::(), user.name); + println!("{}-{}", iter::repeat(INDENTATION).take(depth + 1).collect::(), user); } for child in &channel.children { print_channel(child, depth + 1); diff --git a/mumd/src/state.rs b/mumd/src/state.rs index 4182b6c..2ad88ad 100644 --- a/mumd/src/state.rs +++ b/mumd/src/state.rs @@ -87,7 +87,7 @@ impl State { } let mut server = Server::new(); server.username = Some(username); - server.host = Some(host.clone()); + server.host = Some(format!("{}:{}", host, port)); self.server = Some(server); self.phase_watcher .0 diff --git a/mumlib/src/state.rs b/mumlib/src/state.rs index 01a31ab..96598de 100644 --- a/mumlib/src/state.rs +++ b/mumlib/src/state.rs @@ -1,4 +1,6 @@ use serde::{Deserialize, Serialize}; +use std::fmt::Display; +use serde::export::Formatter; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Server { @@ -18,6 +20,92 @@ pub struct Channel { pub users: Vec, } +impl Channel { + pub fn iter(&self) -> Iter<'_> { + Iter { + me: Some(&self), + channel: if self.children.len() > 0 { Some(0) } else { None }, + channels: self.children.iter().map(|e| e.iter()).collect() + } + } + + pub fn users_iter(&self) -> UsersIter<'_> { + UsersIter { + channels: self.children.iter().map(|e| e.users_iter()).collect(), + channel: if self.children.len() > 0 { Some(0) } else { None }, + user: if self.users.len() > 0 { Some(0) } else { None }, + users: &self.users + } + } +} + +pub struct Iter<'a> { + me: Option<&'a Channel>, + channel: Option, + channels: Vec>, +} + +impl<'a> Iterator for Iter<'a> { + type Item = &'a Channel; + + fn next(&mut self) -> Option { + if self.me.is_some() { + self.me.take() + } else if let Some(mut c) = self.channel { + let mut n = self.channels[c].next(); + while n.is_none() { + c += 1; + if c >= self.channels.len() { + self.channel = None; + return None; + } + n = self.channels[c].next(); + } + self.channel = Some(c); + n + } else { + None + } + } +} + +pub struct UsersIter<'a> { + channel: Option, + channels: Vec>, + user: Option, + users: &'a [User], +} + +impl<'a> Iterator for UsersIter<'a> { + type Item = &'a User; + + fn next(&mut self) -> Option { + if let Some(u) = self.user { + let ret = Some(&self.users[u]); + if u + 1 < self.users.len() { + self.user = Some(u + 1); + } else { + self.user = None; + } + ret + } else if let Some(mut c) = self.channel { + let mut n = self.channels[c].next(); + while n.is_none() { + c += 1; + if c >= self.channels.len() { + self.channel = None; + return None; + } + n = self.channels[c].next(); + } + self.channel = Some(c); + n + } else { + None + } + } +} + #[derive(Clone, Debug, Deserialize, Serialize)] pub struct User { pub comment: Option, @@ -31,4 +119,10 @@ pub struct User { pub self_deaf: bool, // by self pub mute: bool, // by admin pub deaf: bool, // by admin +} + +impl Display for User { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.name) + } } \ No newline at end of file -- cgit v1.2.1