1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
// Copyright 2020-2021 Ian Jackson and contributors to Otter
// SPDX-License-Identifier: AGPL-3.0-or-later
// There is NO WARRANTY.

// This is in this crate for convenience, not because it's to do with
// Z coordinates.

use crate::prelude::*;

pub const SVG_SCALE: f64 = 6.;

pub fn timestring_abbreviate<'x>(base: &str, this: &'x str)
                                 -> (&'x str, bool)
{
  fn split(s: &str) -> ArrayVec<&str, 3> {
    s.splitn(3, ' ').collect()
  }
  let base3 = split(base);
  let this3 = split(this);
  let matches = |i| base3.get(i) == this3.get(i);
  if_chain! {
    if matches(0) && matches(2);
    if let Some(abbrev) = this3.get(1);
    then { (abbrev, true) }
    else { (this, false) }
  }
}

pub fn raw_angle_transform(compass: u8) -> String {
  assert!(compass < 8);
  if compass == 0 { default() }
  else { format!("rotate({})", -45 * (compass as i16)) }
}

pub fn default<T:Default>() -> T { Default::default() }

#[macro_export]
macro_rules! display_as_debug {
  {$x:ty $( , $($gen_tt:tt)* )?} => {
    impl $( $($gen_tt)* )? std::fmt::Display for $x {
      #[throws(std::fmt::Error)]
      fn fmt(&self, f: &mut std::fmt::Formatter) {
        <Self as Debug>::fmt(self, f)?
      }
    }
  }
}
pub use crate::display_as_debug;

pub type SvgAttrs = Vec<(HtmlLit,Html)>;

pub fn space_table_attrs(table_size: PosC<f64>) -> SvgAttrs {
  let PosC { coords: [x, y] } = table_size.into();
  vec![
    (Html::lit("viewBox"), hformat!("0 0 {} {}", x, y) ),
    (Html::lit("width"  ), (SVG_SCALE * x).to_html()  ),
    (Html::lit("height" ), (SVG_SCALE * y).to_html()  ),
  ]
}

pub fn space_rect_attrs(table_size: PosC<f64>) -> SvgAttrs {
  vec![
    (Html::lit("width" ), table_size.x().to_html()  ),
    (Html::lit("height"), table_size.y().to_html()  ),
  ]
}

#[macro_export]
macro_rules! if_let {
  { $($variant:ident)::+ ($binding:pat) = $input:expr;
    else $($otherwise:tt)*
  } => {
    let $binding = match $input {
      $($variant)::+ (y) => y,
      _ => { $($otherwise)* },
    };
  };
  { $($variant:ident)::+ ($binding:pat) = $input:expr;
    $($otherwise:tt)*
  } => {
    let $binding = match $input {
      $($variant)::+  (y) => y,
      $($otherwise)*,
    };
  };
  { $($variant:ident)::+ {$binding:ident} = $input:expr;
    else $($otherwise:tt)*
  } => {
    let $binding = match $input {
      $($variant)::+ { $binding } => $binding,
      _ => { $($otherwise)* },
    };
  };
  { $($variant:ident)::+ {$binding:ident} = $input:expr;
    $($otherwise:tt)*
  } => {
    let $binding = match $input {
      $($variant)::+ { $binding } => $binding,
      $($otherwise)*,
    };
  };
}

#[ext(pub, name=DebugExt)]
impl<T:Debug> T {
  fn to_debug(&self) -> String { format!("{:?}", self) }
}