}
pub fn overlay(&self) -> Option<Activity> {
- match &self.overlay {
- Some(x) => Some(Activity::Overlay(x.clone())),
- _ => None,
- }
+ self.overlay.as_ref().map(|x| Activity::Overlay(x.clone()))
}
pub fn chain_to(&mut self, act: Activity) {
- assert!(!self.overlay.is_some(),
+ assert!(self.overlay.is_none(),
"Don't expect to chain overlay actions");
self.pop();
self.goto(act);
let (url, rsp) = self.api_request(Req::get("v2/instance"))?;
let rspstatus = rsp.status();
let inst: Instance = if !rspstatus.is_success() {
- Err(ClientError::UrlError(url.clone(), rspstatus.to_string()))
+ Err(ClientError::UrlError(url, rspstatus.to_string()))
} else {
match serde_json::from_str(&rsp.text()?) {
Ok(ac) => Ok(ac),
Err(e) => Err(ClientError::UrlError(
- url.clone(), e.to_string())),
+ url, e.to_string())),
}
}?;
self.instance = Some(inst.clone());
fn cache_notification(&mut self, n: &Notification) {
self.cache_account(&n.account);
if let Some(st) = &n.status {
- self.cache_status(&st);
+ self.cache_status(st);
}
self.notifications.insert(n.id.to_string(), n.clone());
}
}?;
if ac.id != id {
return Err(ClientError::UrlError(
- url.clone(), format!("request returned wrong account id {}",
+ url, format!("request returned wrong account id {}",
&ac.id)));
}
self.cache_account(&ac);
}
}
Err(ClientError::UrlError(
- url.clone(), format!(
+ url, format!(
"request did not return expected account id {}", id)))
}
}?;
if st.id != id {
return Err(ClientError::UrlError(
- url.clone(), format!("request returned wrong status id {}",
+ url, format!("request returned wrong status id {}",
&st.id)));
}
self.cache_status(&st);
// we had cached
not.account = ac.clone();
}
- let status_id = match not.status {
- Some(ref st) => Some(&st.id),
- None => None,
- };
+ let status_id = not.status.as_ref().map(|st| &st.id);
if let Some(status_id) = status_id {
if let Some(st) = self.statuses.get(status_id) {
not.status = Some(st.clone());
}?;
if not.id != id {
return Err(ClientError::UrlError(
- url.clone(), format!(
+ url, format!(
"request returned wrong notification id {}", ¬.id)));
}
self.cache_notification(¬);
// below where we did end up retrieving something.
return Ok(false);
}
- } else {
- if !self.feeds.contains_key(id) {
- // We might be called on to extend a feed that we've
- // not yet fetched for the first time, if a streaming
- // notification comes in before the user has yet taken
- // us into the activity reading that feed. If so,
- // ignore the event; the _actual_ initial fetch will
- // deal with it later.
- return Ok(false);
- }
+ } else if !self.feeds.contains_key(id) {
+ // We might be called on to extend a feed that we've
+ // not yet fetched for the first time, if a streaming
+ // notification comes in before the user has yet taken
+ // us into the activity reading that feed. If so,
+ // ignore the event; the _actual_ initial fetch will
+ // deal with it later.
+ return Ok(false);
}
let req = match id {
let req = match ext {
FeedExtend::Initial => req.param("limit", 32),
- FeedExtend::Past => if let Some(ref feed) = self.feeds.get(&id) {
+ FeedExtend::Past => if let Some(feed) = self.feeds.get(id) {
match feed.extend_past {
None => return Ok(false),
Some(ref params) => {
}
}
} else { req },
- FeedExtend::Future => if let Some(ref feed) = self.feeds.get(&id) {
+ FeedExtend::Future => if let Some(feed) = self.feeds.get(id) {
match feed.extend_future {
None => return Ok(false),
Some(ref params) => {
let rspstatus = rsp.status();
if !rspstatus.is_success() {
return Err(ClientError::UrlError(
- url.clone(), rspstatus.to_string()));
+ url, rspstatus.to_string()));
}
// Keep the Link: headers after we consume the response, for
match rsp.headers().get(reqwest::header::LOCATION) {
None => {
return Err(ClientError::UrlError(
- url.clone(),
+ url,
"received redirection without a Location header"
.to_owned()));
}
};
if !ok {
return Err(ClientError::UrlError(
- url.clone(),
+ url,
format!("redirection to suspicious URL {}",
sval)));
}
let rspstatus = rsp.status();
if !rspstatus.is_success() {
return Err(ClientError::UrlError(
- url.clone(), rspstatus.to_string()));
+ url, rspstatus.to_string()));
}
let id = id.clone();
// connection timing out. We don't communicate
// them back to the main thread.
} else {
- let rsp = match std::str::from_utf8(&line) {
+ let rsp = match std::str::from_utf8(line) {
Err(_) => StreamResponse::BadUTF8,
Ok(d) => StreamResponse::Line(d.to_owned()),
};
Req::get("v1/accounts/lookup").param("acct", name))?;
let rspstatus = rsp.status();
let ac: Account = if !rspstatus.is_success() {
- Err(ClientError::UrlError(url.clone(), rspstatus.to_string()))
+ Err(ClientError::UrlError(url, rspstatus.to_string()))
} else {
match serde_json::from_str(&rsp.text()?) {
Ok(ac) => Ok(ac),
Err(e) => Err(ClientError::UrlError(
- url.clone(), e.to_string())),
+ url, e.to_string())),
}
}?;
self.cache_account(&ac);
let (url, rsp) = self.api_request(req)?;
let rspstatus = rsp.status();
if !rspstatus.is_success() {
- Err(ClientError::UrlError(url.clone(), rspstatus.to_string()))
+ Err(ClientError::UrlError(url, rspstatus.to_string()))
} else {
Ok(())
}
let rspstatus = rsp.status();
// Cache the returned status so as to update its faved/boosted flags
let st: Status = if !rspstatus.is_success() {
- Err(ClientError::UrlError(url.clone(), rspstatus.to_string()))
+ Err(ClientError::UrlError(url, rspstatus.to_string()))
} else {
match serde_json::from_str(&rsp.text()?) {
Ok(st) => Ok(st),
Err(e) => {
- Err(ClientError::UrlError(url.clone(), e.to_string()))
+ Err(ClientError::UrlError(url, e.to_string()))
}
}
}?;
&format!("v1/statuses/{id}/context")))?;
let rspstatus = rsp.status();
let ctx: Context = if !rspstatus.is_success() {
- Err(ClientError::UrlError(url.clone(), rspstatus.to_string()))
+ Err(ClientError::UrlError(url, rspstatus.to_string()))
} else {
match serde_json::from_str(&rsp.text()?) {
Ok(st) => Ok(st),
Err(e) => {
- Err(ClientError::UrlError(url.clone(), e.to_string()))
+ Err(ClientError::UrlError(url, e.to_string()))
}
}
}?;
}
pub fn nchars(&self) -> usize { self.text.chars().count() }
- pub fn width(&self) -> usize { UnicodeWidthStr::width(&self.text as &str) }
- pub fn text(&self) -> &'a str { &self.text }
+ pub fn width(&self) -> usize { UnicodeWidthStr::width(self.text as &str) }
+ pub fn text(&self) -> &'a str { self.text }
pub fn truncate(&'a self, width: usize) -> ColouredStringSlice<'a> {
self.split(width).next().unwrap()
type Output = ColouredString;
fn add(self, rhs: ColouredStringSlice<'_>) -> ColouredString {
ColouredString {
- text: self.text.to_owned() + &rhs.text,
- colour: self.colour.to_owned() + &rhs.colour,
+ text: self.text + rhs.text,
+ colour: self.colour + rhs.colour,
}
}
}
}
fn char_width_infallible(c: char) -> usize {
- match UnicodeWidthChar::width(c) {
- Some(w) => w,
- None => 0,
- }
+ UnicodeWidthChar::width(c).unwrap_or(0)
}
impl<'a> Iterator for ColouredStringSplitIterator<'a> {
paste_buffer: "".to_owned(),
};
- assert_eq!(ec.forward(), true);
+ assert!(ec.forward());
assert_eq!(ec.point, 1);
- assert_eq!(ec.forward(), true);
+ assert!(ec.forward());
assert_eq!(ec.point, 3);
- assert_eq!(ec.forward(), true);
+ assert!(ec.forward());
assert_eq!(ec.point, 4);
- assert_eq!(ec.backward(), true);
+ assert!(ec.backward());
assert_eq!(ec.point, 3);
- assert_eq!(ec.backward(), true);
+ assert!(ec.backward());
assert_eq!(ec.point, 1);
- assert_eq!(ec.backward(), true);
+ assert!(ec.backward());
assert_eq!(ec.point, 0);
- assert_eq!(ec.backward(), false);
+ assert!(!ec.backward());
ec.point = ec.text.len() - 2;
- assert_eq!(ec.forward(), true);
+ assert!(ec.forward());
assert_eq!(ec.point, ec.text.len() - 1);
- assert_eq!(ec.forward(), true);
+ assert!(ec.forward());
assert_eq!(ec.point, ec.text.len());
- assert_eq!(ec.forward(), false);
+ assert!(!ec.forward());
assert_eq!(ec.point, ec.text.len());
- assert_eq!(ec.backward(), true);
+ assert!(ec.backward());
assert_eq!(ec.point, ec.text.len() - 1);
- assert_eq!(ec.backward(), true);
+ assert!(ec.backward());
assert_eq!(ec.point, ec.text.len() - 2);
- assert_eq!(ec.backward(), true);
+ assert!(ec.backward());
assert_eq!(ec.point, ec.text.len() - 3);
- assert_eq!(ec.backward(), true);
+ assert!(ec.backward());
assert_eq!(ec.point, ec.text.len() - 5);
- assert_eq!(ec.backward(), true);
+ assert!(ec.backward());
}
#[test]
paste_buffer: "".to_owned(),
};
- assert_eq!(ec.forward_word(), true);
+ assert!(ec.forward_word());
assert_eq!(ec.point, 6); // ipsum
- assert_eq!(ec.forward_word(), true);
+ assert!(ec.forward_word());
assert_eq!(ec.point, 12); // dolor
- assert_eq!(ec.forward_word(), true);
+ assert!(ec.forward_word());
assert_eq!(ec.point, 18); // sit
- assert_eq!(ec.forward_word(), true);
+ assert!(ec.forward_word());
assert_eq!(ec.point, 22); // amet
- assert_eq!(ec.forward_word(), true);
+ assert!(ec.forward_word());
assert_eq!(ec.point, 26); // end of string
- assert_eq!(ec.forward_word(), false);
+ assert!(!ec.forward_word());
- assert_eq!(ec.backward_word(), true);
+ assert!(ec.backward_word());
assert_eq!(ec.point, 22); // amet
- assert_eq!(ec.backward_word(), true);
+ assert!(ec.backward_word());
assert_eq!(ec.point, 18); // sit
- assert_eq!(ec.backward_word(), true);
+ assert!(ec.backward_word());
assert_eq!(ec.point, 12); // dolor
- assert_eq!(ec.backward_word(), true);
+ assert!(ec.backward_word());
assert_eq!(ec.point, 6); // ipsum
- assert_eq!(ec.backward_word(), true);
+ assert!(ec.backward_word());
assert_eq!(ec.point, 0); // lorem
- assert_eq!(ec.backward_word(), false);
+ assert!(!ec.backward_word());
}
#[test]
// But then moving backwards one character goes back over the
// combining char and the printing one before it
- assert_eq!(ec.backward(), true);
+ assert!(ec.backward());
assert_eq!(ec.point, 3);
ec.paste_buffer = "PASTE".to_owned();
_ => { self.core.handle_keypress(key); }
}
self.update_first_visible();
- return false;
+ false
}
pub fn borrow_text(&self) -> &str { &self.core.text }
ColouredString::plain("Examine User: "),
Box::new(move |s, client| {
let s = s.trim();
- let s = s.strip_prefix("@").unwrap_or(s);
+ let s = s.strip_prefix('@').unwrap_or(s);
if s.is_empty() {
LogicalAction::PopOverlaySilent
} else {
ColouredString::plain("View feed for hashtag: "),
Box::new(move |s, _client| {
let s = s.trim();
- let s = s.strip_prefix("#").unwrap_or(s);
+ let s = s.strip_prefix('#').unwrap_or(s);
if s.is_empty() {
LogicalAction::PopOverlaySilent
} else {
// the empty line it left behind. But we don't put that
// boring \n in the paste buffer.
self.core.delete(self.core.point, eol_pos);
- } else if slice.ends_with("\n") {
+ } else if slice.ends_with('\n') {
// If the slice goes up to but not including a \n,
// literally cut everything up to but not including the
// end of the line.
let detect_magic_sequence = |seq: &str| {
self.core.text[..self.core.point].ends_with(seq) &&
(self.core.point == seq.len() ||
- self.core.text[..self.core.point - seq.len()].ends_with("\n"))
+ self.core.text[..self.core.point - seq.len()].ends_with('\n'))
};
if detect_magic_sequence(".\n") {
}
fn submit_post(&self) -> LogicalAction {
- return LogicalAction::PostComposed(Post {
+ LogicalAction::PostComposed(Post {
text: self.core.text.clone(),
m: self.post_metadata.clone(),
})
match (self.keystate, key) {
(Start, Ctrl('N')) | (Start, Down) |
(Start, Ctrl('P')) | (Start, Up) => {
- if !self.goal_column.is_some() {
+ if self.goal_column.is_none() {
self.goal_column = self.cursor_pos.map(|(x, _y)| x);
}
}
Some(ref id) => format!("Reply to post {id}"),
};
let header = FileHeader::new(ColouredString::uniform(&title, 'H'));
- let irt = match post.m.in_reply_to_id {
- None => None,
- Some(ref id) => Some(InReplyToLine::from_id(id, client)),
- };
+ let irt = post.m.in_reply_to_id.as_ref()
+ .map(|id| InReplyToLine::from_id(id, client));
Ok(Box::new(Composer::new(inst.configuration.statuses, header, irt, post)))
}
impl FileDataSource for FeedSource {
fn get(&self, client: &mut Client) -> (Vec<String>, isize) {
let feed = client.borrow_feed(&self.id);
- let ids = feed.ids.iter().map(|x| x.clone()).collect();
+ let ids = feed.ids.iter().cloned().collect();
(ids, feed.origin)
}
fn get_from_client(id: &str, client: &mut Client) ->
Result<Self::Item, ClientError>
{
- let st = client.status_by_id(&id)?;
- Ok(StatusDisplay::new(st.clone(), client))
+ let st = client.status_by_id(id)?;
+ Ok(StatusDisplay::new(st, client))
}
fn feed_id(&self) -> Option<&FeedId> { self.id.as_ref() }
fn get_from_client(id: &str, client: &mut Client) ->
Result<Self::Item, ClientError>
{
- let not = client.notification_by_id(&id)?;
+ let not = client.notification_by_id(id)?;
let st = ¬.status.expect(
"expected all notifications in this feed would have statuses");
Ok(StatusDisplay::new(st.clone(), client))
fn get_from_client(id: &str, client: &mut Client) ->
Result<Self::Item, ClientError>
{
- let not = client.notification_by_id(&id)?;
+ let not = client.notification_by_id(id)?;
Ok(NotificationLog::from_notification(¬, client))
}
fn get_from_client(id: &str, client: &mut Client) ->
Result<Self::Item, ClientError>
{
- let ac = client.account_by_id(&id)?;
+ let ac = client.account_by_id(id)?;
Ok(UserListEntry::from_account(&ac, client))
}
}
}
}
- if lines_rendered + 1 <= h {
+ if lines_rendered < h {
Some(h - 1 - lines_rendered)
} else {
None
let (w, _h) = self.last_size.expect(
"ensure_enough_rendered before setting pos");
let at_top = self.at_top();
- match &mut self.contents.extender {
- Some(ref mut ext) => {
- ext.set_primed(at_top);
- }
- _ => (),
- };
+ if let Some(ref mut ext) = &mut self.contents.extender {
+ ext.set_primed(at_top);
+ }
if let Some(ei) = self.contents.extender_index() {
self.rendered.remove(&ei);
self.ensure_item_rendered(ei, w);
}
fn update_pos_for_size(&mut self, w: usize, h: usize) {
- if self.pos.width == None && self.pos.line == 0 {
+ if self.pos.width.is_none() && self.pos.line == 0 {
// Special case: look at the _top_ of the item
self.pos.width = Some(w);
self.move_down(h.saturating_sub(1));
self.rerender_selected_item();
self.ensure_enough_rendered();
LogicalAction::Nothing
+ } else if none_ok {
+ LogicalAction::Nothing
} else {
- if none_ok {
- LogicalAction::Nothing
- } else {
- LogicalAction::Beep
- }
+ LogicalAction::Beep
};
self.select_aux = match self.ui_mode {
fn search(&mut self) -> LogicalAction {
if let Some(dir) = self.search_direction {
- if !self.last_search.is_some() {
+ if self.last_search.is_none() {
return LogicalAction::Beep;
}
fs.add(Pr('Q'), "Quit", 100)
}
UIMode::PostsSubmenu => {
- assert_eq!(Type::CAN_GET_POSTS, true,
- "How did we get here if !CAN_GET_POSTS?");
+ assert!(Type::CAN_GET_POSTS,
+ "How did we get here if !CAN_GET_POSTS?");
fs.add(Pr('A'), "All", 99)
.add(Pr('O'), "Original", 97)
.add(Pr('T'), "Top-level", 98)
pub fn list_user_followers(client: &mut Client, id: &str) ->
Result<Box<dyn ActivityState>, ClientError>
{
- let ac = client.account_by_id(&id)?;
+ let ac = client.account_by_id(id)?;
let name = client.fq(&ac.acct);
let file = File::new(
pub fn list_user_followees(client: &mut Client, id: &str) ->
Result<Box<dyn ActivityState>, ClientError>
{
- let ac = client.account_by_id(&id)?;
+ let ac = client.account_by_id(id)?;
let name = client.fq(&ac.acct);
let file = File::new(
let title = ColouredString::uniform(
&format!("Posts mentioning hashtag #{tag}"), 'H');
let feed = FeedId::Hashtag(tag.to_owned());
- let desc = StatusFeedType::with_feed(feed.clone());
+ let desc = StatusFeedType::with_feed(feed);
let file = File::new(
client, FeedSource::new(FeedId::Hashtag(tag.to_owned())), title,
desc, None)?;
Result<Self::Item, ClientError>
{
let ac = client.account_by_id(id)?;
- Ok(ExamineUserDisplay::new(ac, client)?)
+ ExamineUserDisplay::new(ac, client)
}
}
fn get_from_client(id: &str, client: &mut Client) ->
Result<Self::Item, ClientError>
{
- let st = client.status_by_id(&id)?;
- Ok(DetailedStatusDisplay::new(st.clone(), client))
+ let st = client.status_by_id(id)?;
+ Ok(DetailedStatusDisplay::new(st, client))
}
}
let file = File::new(
client, StaticSource::vector(ids), title,
StatusFeedType::without_feed(),
- Some(FilePosition::item_top(index as isize)))?;
+ Some(FilePosition::item_top(index)))?;
Ok(Box::new(file))
}
/// Return a suffix for after a link.
fn decorate_link_end(&mut self) -> String {
if let Some(url) = self.current_url.take() {
- if let Some(ref rc) = self.urls {
+ if let Some(rc) = self.urls {
// This is safe because the borrow only lasts for the
// duration of this Vec::push, and it's the only
// borrow_mut of this RefCell anywhere, so nothing is
/// Return a new decorator of the same type which can be used
/// for sub blocks.
fn make_subblock_decorator(&self) -> Self {
- OurDecorator::with_option_urls(self.urls.clone())
+ OurDecorator::with_option_urls(self.urls)
}
/// Return an annotation corresponding to adding colour, or none.
let mut w = width;
loop {
w += w / 2;
- if let Ok(_) = try_render(rt, width, w) {
+ if try_render(rt, width, w).is_ok() {
break w;
}
}
while wgood - wbad > 1 {
let wmid = wbad + (wgood - wbad) / 2;
- if let Ok(_) = try_render(rt, width, wmid) {
+ if try_render(rt, width, wmid).is_ok() {
wgood = wmid;
} else {
wbad = wmid;
fn to_coloured_string(tl: &TaggedLine<Vec<char>>) -> ColouredString {
let mut cs = ColouredString::plain("");
for e in tl.iter() {
- match e {
- TaggedLineElement::Str(ts) => {
- let c: char = match ts.tag.first() {
- Some(c) => *c,
- None => ' ',
- };
- cs.push_str(&ColouredString::uniform(&ts.s, c).slice());
- }
- _ => (),
+ if let TaggedLineElement::Str(ts) = e {
+ let c: char = match ts.tag.first() {
+ Some(c) => *c,
+ None => ' ',
+ };
+ cs.push_str(&ColouredString::uniform(&ts.s, c).slice());
}
}
cs
}
use AppTokenType::*;
-const REDIRECT_MAGIC_STRING: &'static str = "urn:ietf:wg:oauth:2.0:oob";
+const REDIRECT_MAGIC_STRING: &str = "urn:ietf:wg:oauth:2.0:oob";
impl Login {
fn new(instance_url: &str, logfile: Option<File>)
let rsp = self.execute_request(req)?;
let rspstatus = rsp.status();
if !rspstatus.is_success() {
- Err(ClientError::UrlError(url.clone(), rspstatus.to_string()))
+ Err(ClientError::UrlError(url, rspstatus.to_string()))
} else {
let app: Application = match serde_json::from_str(&rsp.text()?) {
Ok(app) => Ok(app),
- Err(e) => Err(ClientError::UrlError(
- url.clone(), e.to_string())),
+ Err(e) => Err(ClientError::UrlError(url, e.to_string())),
}?;
Ok(app)
}
let rsp = self.execute_request(req)?;
let rspstatus = rsp.status();
if !rspstatus.is_success() {
- Err(ClientError::UrlError(url.clone(), rspstatus.to_string()))
+ Err(ClientError::UrlError(url, rspstatus.to_string()))
} else {
let tok: Token = match serde_json::from_str(&rsp.text()?) {
Ok(tok) => Ok(tok),
- Err(e) => Err(ClientError::UrlError(
- url.clone(), e.to_string())),
+ Err(e) => Err(ClientError::UrlError(url, e.to_string())),
}?;
Ok(tok)
}
let rsp = self.execute_request(req)?;
let rspstatus = rsp.status();
if !rspstatus.is_success() {
- Err(ClientError::UrlError(url.clone(), rspstatus.to_string()))
+ Err(ClientError::UrlError(url, rspstatus.to_string()))
} else {
let tok: T = match serde_json::from_str(&rsp.text()?) {
Ok(tok) => Ok(tok),
- Err(e) => Err(ClientError::UrlError(
- url.clone(), e.to_string())),
+ Err(e) => Err(ClientError::UrlError(url, e.to_string())),
}?;
Ok(tok)
}
// Print it
println!("Log in to the website {instance_url}/");
println!("and then visit this URL to authorise Mastodonochrome:");
- println!("");
+ println!();
println!("{}", url);
- println!("");
+ println!();
println!("If you click \"Authorise\" on that page, you should receive a response code.");
print!("Enter that code here: ");
std::io::stdout().flush().unwrap(); // FIXME
std::io::stdin().read_line(&mut buf).unwrap(); // FIXME
buf
};
- let code = (&code).trim_end();
+ let code = code.trim_end();
// Use that code to get the final user access token
let user_token = login.get_token(&app, AuthorizationCode(code))?;
let instance: Instance = login.get("/api/v2/instance",
&user_token.access_token)?;
- println!("");
+ println!();
println!("Successfully logged in as {}@{}", account.username, instance.domain);
println!("Now run 'mastodonochrome' without arguments to read and post!");
match main_inner() {
Ok(_) => ExitCode::from(0),
Err(e) => {
- let _ = eprintln!("{}", e);
+ eprintln!("{}", e);
ExitCode::from(1)
}
}
fn default_language() -> String {
get_locale().as_deref()
.and_then(|s| s.split('-').next())
- .map(|s| if s.len() == 0 { "en" } else { s })
+ .map(|s| if s.is_empty() { "en" } else { s })
.unwrap_or("en")
.to_owned()
}
check_widths(&Self::visibility_item(vis));
}
if let Some(ref ml) = self.editor_prompt {
- check_widths(&ml);
+ check_widths(ml);
}
self.ml_post.reset_widths();
pub fn get_span(&self, text: &str, start: usize) -> Option<(usize, usize)> {
let mut start = start;
loop {
- match self.text.find_at(&text, start) {
+ match self.text.find_at(text, start) {
None => break None,
Some(m) => {
let (ms, me) = (m.start(), m.end());
let mention_bad_pre = Regex::new(&("[=/".to_owned() + word + "]$"))
.unwrap();
let mention = Regex::new(
- &("(?i:@((".to_owned() + &username + ")(?:@[" + &word + ".-]+[" +
- &word + "]+)?))")).unwrap();
+ &("(?i:@((".to_owned() + username + ")(?:@[" + word + ".-]+[" +
+ word + "]+)?))")).unwrap();
let hashtag_separators = "_\u{B7}\u{30FB}\u{200C}";
let word_hash_sep = word.to_owned() + "#" + hashtag_separators;
let domain = domain_component.to_owned() + "(?:\\." +
&domain_component + ")*";
- let path_end_chars = "a-z".to_owned() + &cyrillic + &accented +
+ let path_end_chars = "a-z".to_owned() + cyrillic + accented +
"0-9=_#/\\+\\-";
- let path_mid_chars = path_end_chars.to_owned() + &pd +
+ let path_mid_chars = path_end_chars.to_owned() + pd +
"!\\*\\';:\\,\\.\\$\\%\\[\\]~&\\|@";
let path_bracketed_once = "\\([".to_owned() +
"!?\\*\\'\\(\\);:\\+\\$%\\[\\]\\.,~|@";
let url_bad_pre = Regex::new(
- &("[A-Z0-9@$#\u{FF20}\u{FF03}".to_owned() + &directional + "]$"))
+ &("[A-Z0-9@$#\u{FF20}\u{FF03}".to_owned() + directional + "]$"))
.unwrap();
let url = Regex::new(
&("(?i:".to_owned() +
fn highlighted_id(&self, highlight: Option<Highlight>) -> Option<String> {
let mut highlight = highlight;
for item in self {
- match item.highlighted_id_update(&mut highlight) {
- result @ Some(..) => return result,
- _ => (),
+ if let result @ Some(..) = item.highlighted_id_update(
+ &mut highlight)
+ {
+ return result;
}
}
None
let mut suffix = ColouredString::plain("");
let display_pre = ColouredString::uniform("[", 'S');
let display_post = ColouredString::uniform("]--", 'S');
- match self.timestamp {
- Some(date) => {
- let datestr = format_date(date);
- suffix = &display_pre +
- ColouredString::uniform(&datestr, 'D') +
- &display_post + suffix;
- }
- _ => (),
+ if let Some(date) = self.timestamp {
+ let datestr = format_date(date);
+ suffix = &display_pre +
+ ColouredString::uniform(&datestr, 'D') +
+ &display_post + suffix;
}
if self.boosted {
suffix = &display_pre + ColouredString::uniform("B", 'D') +
{
vec! {
ColouredString::uniform(
- &((&"-".repeat(width - min(2, width))).to_owned() + "|"),
+ &("-".repeat(width - min(2, width)) + "|"),
'-',
).truncate(width).to_owned(),
}
let currlen = para.words.len();
para.push_para(&post);
para.delete_mention_words_from(currlen);
- InReplyToLine {
- para: para
- }
+ InReplyToLine { para }
}
pub fn from_id(id: &str, client: &mut Client) -> Self {
para.delete_mention_words_from(currlen);
}
- let status_id = match status_id {
- None => None,
- Some(s) => Some(s.to_owned()),
- };
+ let status_id = status_id.map(|s| s.to_owned());
NotificationLog {
timestamp,
}
pub fn from_notification(not: &Notification, client: &mut Client) -> Self {
- let para = match ¬.status {
- None => None,
- Some(st) => Some(Html::new(&st.content).to_para()),
- };
- let status_id = match ¬.status {
- None => None,
- Some(st) => Some(&st.id as &str),
- };
+ let para = not.status.as_ref()
+ .map(|st| Html::new(&st.content).to_para());
+ let status_id = not.status.as_ref().map(|st| &st.id as &str);
Self::new(
not.created_at,
&client.fq(¬.account.acct),
FileStatusLineFinal {
fs: self,
- priwidth: priwidth
+ priwidth,
}
}
}
};
if let Some(msg) = &self.fs.message {
- let cmsg = ColouredString::plain(&msg);
+ let cmsg = ColouredString::plain(msg);
push(&mut line, cmsg.slice());
}
- let cprop = if let Some(prop) = &self.fs.proportion {
- Some(ColouredString::plain(&format!("({}%)", prop)))
- } else {
- None
- };
+ let cprop = self.fs.proportion.as_ref()
+ .map(|prop| ColouredString::plain(&format!("({}%)", prop)));
let cpropwidth = if let Some(cprop) = &cprop { cprop.width() } else {0};
let extraspace = if !line.is_empty() && cpropwidth > 0 {
FileStatusLine::SPACING
- } else if !cprop.is_some() {
+ } else if cprop.is_none() {
1 // trailing '.' if no proportion
} else {
0
&booster.id)),
};
- let irt = match &st.in_reply_to_id {
- None => None,
- Some(id) => Some(InReplyToLine::from_id(id, client)),
- };
+ let irt = st.in_reply_to_id.as_ref()
+ .map(|id| InReplyToLine::from_id(id, client));
let vis = match st.visibility {
Visibility::Public => None,
let content = Html::new(&st.content);
let media = st.media_attachments.iter().map(|m| {
- let desc_ref = match &m.description {
- Some(s) => Some(&s as &str),
- None => None,
- };
+ let desc_ref = m.description.as_ref().map(|s| s as &str);
Media::new(&m.url, desc_ref)
}).collect();
content,
media,
blank: BlankLine::new(),
- id: st.id.clone(),
+ id: st.id,
}
}
push_fragment(&mut lines, self.irt.render(width));
push_fragment(&mut lines, self.blank.render(width));
let rendered_content = self.content.render(width);
- let content_empty = rendered_content.len() == 0;
+ let content_empty = rendered_content.is_empty();
push_fragment_opt_highlight(&mut lines, rendered_content);
if !content_empty {
push_fragment(&mut lines, self.blank.render(width));
match highlight {
Some(Highlight(HighlightType::User, _)) => {
let mut highlight = highlight;
- match self.from.highlighted_id_update(&mut highlight) {
- result @ Some(..) => return result,
- _ => (),
+ if let result @ Some(..) = self.from.highlighted_id_update(
+ &mut highlight)
+ {
+ return result;
}
- match self.via.highlighted_id_update(&mut highlight) {
- result @ Some(..) => return result,
- _ => (),
+ if let result @ Some(..) = self.via.highlighted_id_update(
+ &mut highlight)
+ {
+ return result;
}
None
}
let client_url = Paragraph::new()
.add(&ColouredString::plain("Client website: "))
.add(&st.application.as_ref()
- .map_or(None, |app| app.website.as_ref())
+ .and_then(|app| app.website.as_ref())
.map_or_else(
|| ColouredString::uniform("none", '0'),
- |url| ColouredString::uniform(&url, 'u')));
+ |url| ColouredString::uniform(url, 'u')));
let sd = StatusDisplay::new(st, client);
let urls: Vec<_> = sd.list_urls().iter().map(|u| {
Paragraph::new().set_indent(2, 4)
- .add(&ColouredString::uniform(&u, 'u'))
+ .add(&ColouredString::uniform(u, 'u'))
}).collect();
let urls_header = if urls.is_empty() {
None
-> Option<String>
{
let mut highlight = highlight;
- match self.sd.highlighted_id_update(&mut highlight) {
- result @ Some(..) => return result,
- _ => (),
+ if let result @ Some(..) = self.sd.highlighted_id_update(
+ &mut highlight)
+ {
+ return result;
}
match highlight {
let info_fields = ac.fields.iter().map(|field| {
let colour = if field.verified_at.is_some() { 'f' } else { ' ' };
let title_text = field.name.trim();
- let title_text = title_text.strip_suffix(":").unwrap_or(title_text);
+ let title_text = title_text.strip_suffix(':').unwrap_or(title_text);
let title_text = title_text.to_owned() + ":";
let title = Paragraph::new()
.add(&ColouredString::uniform(&title_text, colour))
&format!("Unable to retrieve relationships: {}", e),
'!'))),
}
- if relationships.len() > 0 {
+ if !relationships.is_empty() {
relationships.insert(0, Paragraph::new().add(
&ColouredString::plain("Relationships to this user:")));
}
// I don't think we have any need to join subthreads like this
let _joinhandle = std::thread::spawn(move || {
while let Ok(ev) = event::read() {
- if let Err(_) = input_sender.send(SubthreadEvent::TermEv(ev)) {
+ if input_sender.send(SubthreadEvent::TermEv(ev)).is_err() {
break;
}
}
let sender = self.subthread_sender.clone();
self.client.start_streaming_thread(
&StreamId::User, Box::new(move |update| {
- if let Err(_) = sender.send(
- SubthreadEvent::StreamEv(update)) {
+ if sender.send(
+ SubthreadEvent::StreamEv(update)).is_err() {
// It would be nice to do something about this
// error, but what _can_ we do? We can hardly send
// an error notification back to the main thread,
NonUtilityActivity::ComposeToplevel) =>
NonUtilityActivity::PostComposeMenu.into(),
Activity::Util(UtilityActivity::ComposeReply(id)) =>
- UtilityActivity::PostReplyMenu(id.clone()).into(),
+ UtilityActivity::PostReplyMenu(id).into(),
act => panic!("can't postcompose {act:?}"),
};
self.activity_stack.chain_to(newact);
Activity::NonUtil(NonUtilityActivity::PostComposeMenu) =>
NonUtilityActivity::ComposeToplevel.into(),
Activity::Util(UtilityActivity::PostReplyMenu(id)) =>
- UtilityActivity::ComposeReply(id.clone()).into(),
+ UtilityActivity::ComposeReply(id).into(),
act => panic!("can't reedit {act:?}"),
};
self.activity_stack.chain_to(newact);
Activity::Util(UtilityActivity::InfoStatus(ref id)) =>
view_single_post(client, id),
Activity::NonUtil(NonUtilityActivity::ComposeToplevel) =>
- compose_post(client, post.unwrap_or_else(|| Post::new())),
+ compose_post(client, post.unwrap_or_else(Post::new)),
Activity::NonUtil(NonUtilityActivity::PostComposeMenu) =>
Ok(post_menu(post.expect(
"how did we get here without a Post?"))),