mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
simplify
This commit is contained in:
parent
d7bbc2a412
commit
e3a3962130
15 changed files with 74 additions and 81 deletions
|
|
@ -1,9 +1,9 @@
|
||||||
(@esc cancel-dialog)
|
(@esc dialog :dialog-none)
|
||||||
(@f1 toggle-dialog :dialog-help)
|
(@f1 dialog :dialog-help)
|
||||||
(@f6 toggle-dialog :dialog-save)
|
(@f6 dialog :dialog-save)
|
||||||
(@f8 toggle-dialog :dialog-options)
|
(@f8 dialog :dialog-options)
|
||||||
(@f9 toggle-dialog :dialog-load)
|
(@f9 dialog :dialog-load)
|
||||||
(@f10 toggle-dialog :dialog-quit)
|
(@f10 dialog :dialog-quit)
|
||||||
|
|
||||||
(@u undo 1)
|
(@u undo 1)
|
||||||
(@r redo 1)
|
(@r redo 1)
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm
|
||||||
}));
|
}));
|
||||||
|
|
||||||
#[tengri_proc::command(App)] impl AppCommand {
|
#[tengri_proc::command(App)] impl AppCommand {
|
||||||
fn toggle_dialog (app: &mut App, dialog: Dialog) -> Perhaps<Self> {
|
fn dialog (app: &mut App, dialog: Option<Dialog>) -> Perhaps<Self> {
|
||||||
app.toggle_dialog(Some(dialog));
|
app.toggle_dialog(dialog);
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn cancel_dialog (app: &mut App) -> Perhaps<Self> {
|
fn cancel_dialog (app: &mut App) -> Perhaps<Self> {
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,9 @@
|
||||||
#![feature(type_changing_struct_update)]
|
#![feature(type_changing_struct_update)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(closure_lifetime_binder)]
|
#![feature(closure_lifetime_binder)]
|
||||||
/// Standard result type.
|
|
||||||
pub type Usually<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
|
||||||
/// Standard optional result type.
|
|
||||||
pub type Perhaps<T> = std::result::Result<Option<T>, Box<dyn std::error::Error>>;
|
|
||||||
pub use ::tek_engine:: *;
|
pub use ::tek_engine:: *;
|
||||||
pub use ::tek_device::{self, *};
|
pub use ::tek_device::{self, *};
|
||||||
|
pub use ::tengri::{Usually, Perhaps, Has};
|
||||||
pub use ::tengri::dsl::*;
|
pub use ::tengri::dsl::*;
|
||||||
pub use ::tengri::input::*;
|
pub use ::tengri::input::*;
|
||||||
pub use ::tengri::output::*;
|
pub use ::tengri::output::*;
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ has!(Vec<JackMidiIn>: |self: App|self.project.midi_ins);
|
||||||
has!(Vec<JackMidiOut>: |self: App|self.project.midi_outs);
|
has!(Vec<JackMidiOut>: |self: App|self.project.midi_outs);
|
||||||
has!(Vec<Scene>: |self: App|self.project.scenes);
|
has!(Vec<Scene>: |self: App|self.project.scenes);
|
||||||
has!(Vec<Track>: |self: App|self.project.tracks);
|
has!(Vec<Track>: |self: App|self.project.tracks);
|
||||||
|
has!(Measure<TuiOut>: |self: App|self.size);
|
||||||
|
|
||||||
has_size!(<TuiOut>|self: App|&self.size);
|
|
||||||
has_clips!(|self: App|self.project.pool.clips);
|
has_clips!(|self: App|self.project.pool.clips);
|
||||||
has_editor!(|self: App|{
|
has_editor!(|self: App|{
|
||||||
editor = self.editor;
|
editor = self.editor;
|
||||||
|
|
@ -152,8 +152,8 @@ impl App {
|
||||||
/// Various possible dialog overlays
|
/// Various possible dialog overlays
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Dialog {
|
pub enum Dialog {
|
||||||
Help,
|
Help(usize),
|
||||||
Menu,
|
Menu(usize),
|
||||||
Device(usize),
|
Device(usize),
|
||||||
Message(Message),
|
Message(Message),
|
||||||
Save(Browser),
|
Save(Browser),
|
||||||
|
|
@ -216,29 +216,32 @@ impl App {
|
||||||
fn focus_pool_length (&self) -> bool {
|
fn focus_pool_length (&self) -> bool {
|
||||||
matches!(self.project.pool.mode, Some(PoolMode::Length(..)))
|
matches!(self.project.pool.mode, Some(PoolMode::Length(..)))
|
||||||
}
|
}
|
||||||
fn dialog_device (&self) -> Dialog {
|
fn dialog_none (&self) -> Option<Dialog> {
|
||||||
Dialog::Device(0) // TODO
|
None
|
||||||
}
|
}
|
||||||
fn dialog_device_prev (&self) -> Dialog {
|
fn dialog_device (&self) -> Option<Dialog> {
|
||||||
Dialog::Device(0) // TODO
|
Some(Dialog::Device(0)) // TODO
|
||||||
}
|
}
|
||||||
fn dialog_device_next (&self) -> Dialog {
|
fn dialog_device_prev (&self) -> Option<Dialog> {
|
||||||
Dialog::Device(0) // TODO
|
Some(Dialog::Device(0)) // TODO
|
||||||
}
|
}
|
||||||
fn dialog_help (&self) -> Dialog {
|
fn dialog_device_next (&self) -> Option<Dialog> {
|
||||||
Dialog::Help
|
Some(Dialog::Device(0)) // TODO
|
||||||
}
|
}
|
||||||
fn dialog_menu (&self) -> Dialog {
|
fn dialog_help (&self) -> Option<Dialog> {
|
||||||
Dialog::Menu
|
Some(Dialog::Help(0))
|
||||||
}
|
}
|
||||||
fn dialog_save (&self) -> Dialog {
|
fn dialog_menu (&self) -> Option<Dialog> {
|
||||||
Dialog::Save(Default::default())
|
Some(Dialog::Menu(0))
|
||||||
}
|
}
|
||||||
fn dialog_load (&self) -> Dialog {
|
fn dialog_save (&self) -> Option<Dialog> {
|
||||||
Dialog::Load(Default::default())
|
Some(Dialog::Save(Default::default()))
|
||||||
}
|
}
|
||||||
fn dialog_options (&self) -> Dialog {
|
fn dialog_load (&self) -> Option<Dialog> {
|
||||||
Dialog::Options
|
Some(Dialog::Load(Default::default()))
|
||||||
|
}
|
||||||
|
fn dialog_options (&self) -> Option<Dialog> {
|
||||||
|
Some(Dialog::Options)
|
||||||
}
|
}
|
||||||
fn editor_pitch (&self) -> Option<u7> {
|
fn editor_pitch (&self) -> Option<u7> {
|
||||||
Some((self.editor().as_ref().map(|e|e.get_note_pos()).unwrap() as u8).into())
|
Some((self.editor().as_ref().map(|e|e.get_note_pos()).unwrap() as u8).into())
|
||||||
|
|
|
||||||
|
|
@ -58,10 +58,10 @@ impl App {
|
||||||
Fixed::xy(70, 23, Tui::fg_bg(Rgb(255,255,255), Rgb(16,16,16), Bsp::b(
|
Fixed::xy(70, 23, Tui::fg_bg(Rgb(255,255,255), Rgb(16,16,16), Bsp::b(
|
||||||
Repeat(" "), Outer(true, Style::default().fg(Tui::g(96)))
|
Repeat(" "), Outer(true, Style::default().fg(Tui::g(96)))
|
||||||
.enclose(self.dialog.as_ref().map(|dialog|match dialog {
|
.enclose(self.dialog.as_ref().map(|dialog|match dialog {
|
||||||
Dialog::Menu =>
|
Dialog::Menu(_) =>
|
||||||
self.view_dialog_menu().boxed(),
|
self.view_dialog_menu().boxed(),
|
||||||
Dialog::Help =>
|
Dialog::Help(offset) =>
|
||||||
self.view_dialog_help().boxed(),
|
self.view_dialog_help(*offset).boxed(),
|
||||||
Dialog::Save(browser) =>
|
Dialog::Save(browser) =>
|
||||||
self.view_dialog_save().boxed(),
|
self.view_dialog_save().boxed(),
|
||||||
Dialog::Load(browser) =>
|
Dialog::Load(browser) =>
|
||||||
|
|
@ -84,12 +84,13 @@ impl App {
|
||||||
let option = |a,i|Tui::fg(Rgb(255,255,255), format!("{}", a));
|
let option = |a,i|Tui::fg(Rgb(255,255,255), format!("{}", a));
|
||||||
Bsp::s(Tui::bold(true, "tek!"), Bsp::s("", Map::south(1, options, option)))
|
Bsp::s(Tui::bold(true, "tek!"), Bsp::s("", Map::south(1, options, option)))
|
||||||
}
|
}
|
||||||
pub fn view_dialog_help <'a> (&'a self) -> impl Content<TuiOut> + use<'a> {
|
pub fn view_dialog_help <'a> (&'a self, offset: usize) -> impl Content<TuiOut> + use<'a> {
|
||||||
Bsp::s(Tui::bold(true, "Help"), Bsp::s("", Map::south(1,
|
Bsp::s(Tui::bold(true, "Help"), Bsp::s("", Map::south(1,
|
||||||
||self.config.keys.layers.iter()
|
move||self.config.keys.layers.iter()
|
||||||
.filter_map(|a|(a.0)(self).then_some(a.1))
|
.filter_map(|a|(a.0)(self).then_some(a.1))
|
||||||
.flat_map(|a|a)
|
.flat_map(|a|a)
|
||||||
.filter_map(|x|if let Value::Exp(_, iter)=x.value{ Some(iter) } else { None })
|
.filter_map(|x|if let Value::Exp(_, iter)=x.value{ Some(iter) } else { None })
|
||||||
|
.skip(offset)
|
||||||
.take(20),
|
.take(20),
|
||||||
|mut b,i|Fixed::x(60, Align::w(Bsp::e("(", Bsp::e(
|
|mut b,i|Fixed::x(60, Align::w(Bsp::e("(", Bsp::e(
|
||||||
b.next().map(|t|Fixed::x(16, Align::w(Tui::fg(Rgb(64,224,0), format!("{}", t.value))))),
|
b.next().map(|t|Fixed::x(16, Align::w(Tui::fg(Rgb(64,224,0), format!("{}", t.value))))),
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ has!(Vec<JackMidiIn>: |self: Arrangement|self.midi_ins);
|
||||||
has!(Vec<JackMidiOut>: |self: Arrangement|self.midi_outs);
|
has!(Vec<JackMidiOut>: |self: Arrangement|self.midi_outs);
|
||||||
has!(Vec<Scene>: |self: Arrangement|self.scenes);
|
has!(Vec<Scene>: |self: Arrangement|self.scenes);
|
||||||
has!(Vec<Track>: |self: Arrangement|self.tracks);
|
has!(Vec<Track>: |self: Arrangement|self.tracks);
|
||||||
|
has!(Measure<TuiOut>: |self: Arrangement|self.size);
|
||||||
|
|
||||||
impl Arrangement {
|
impl Arrangement {
|
||||||
/// Width of display
|
/// Width of display
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ impl<'a> ArrangerView<'a> {
|
||||||
pub(crate) fn input_ports (&'a self) -> impl Content<TuiOut> + 'a {
|
pub(crate) fn input_ports (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
Tryptich::top(1)
|
Tryptich::top(1)
|
||||||
.left(self.width_side,
|
.left(self.width_side,
|
||||||
button_3("i", "midi ins", format!("{}", self.inputs_count), self.is_editing))
|
button_3("i", "midi ins", format!("{}", self.arrangement.midi_ins().len()), self.is_editing))
|
||||||
.right(self.width_side,
|
.right(self.width_side,
|
||||||
button_2("I", "add midi in", self.is_editing))
|
button_2("I", "add midi in", self.is_editing))
|
||||||
.middle(self.width_mid,
|
.middle(self.width_mid,
|
||||||
|
|
@ -96,7 +96,12 @@ impl<'a> ArrangerView<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn output_count (&'a self) -> impl Content<TuiOut> + 'a {
|
pub(crate) fn output_count (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
button_3("o", "midi outs", format!("{}", self.outputs_count), self.is_editing)
|
button_3(
|
||||||
|
"o",
|
||||||
|
"midi outs",
|
||||||
|
format!("{}", self.arrangement.midi_outs().len()),
|
||||||
|
self.is_editing
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn output_add (&'a self) -> impl Content<TuiOut> + 'a {
|
pub(crate) fn output_add (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
|
|
|
||||||
|
|
@ -9,20 +9,15 @@ pub struct ArrangerView<'a> {
|
||||||
pub width_mid: u16,
|
pub width_mid: u16,
|
||||||
pub width_side: u16,
|
pub width_side: u16,
|
||||||
|
|
||||||
pub inputs_count: usize,
|
|
||||||
pub inputs_height: u16,
|
pub inputs_height: u16,
|
||||||
|
|
||||||
pub outputs_count: usize,
|
|
||||||
pub outputs_height: u16,
|
pub outputs_height: u16,
|
||||||
|
|
||||||
pub scene_last: usize,
|
pub scene_last: usize,
|
||||||
pub scene_count: usize,
|
|
||||||
pub scene_scroll: Fill<Fixed<u16, ScrollbarV>>,
|
pub scene_scroll: Fill<Fixed<u16, ScrollbarV>>,
|
||||||
pub scene_selected: Option<usize>,
|
pub scene_selected: Option<usize>,
|
||||||
pub scenes_height: u16,
|
pub scenes_height: u16,
|
||||||
|
|
||||||
pub track_scroll: Fill<Fixed<u16, ScrollbarH>>,
|
pub track_scroll: Fill<Fixed<u16, ScrollbarH>>,
|
||||||
pub track_count: usize,
|
|
||||||
pub track_selected: Option<usize>,
|
pub track_selected: Option<usize>,
|
||||||
pub tracks_height: u16,
|
pub tracks_height: u16,
|
||||||
|
|
||||||
|
|
@ -47,14 +42,10 @@ impl<'a> ArrangerView<'a> {
|
||||||
width_side: arrangement.w_sidebar(is_editing),
|
width_side: arrangement.w_sidebar(is_editing),
|
||||||
|
|
||||||
inputs_height: arrangement.h_inputs(),
|
inputs_height: arrangement.h_inputs(),
|
||||||
inputs_count: arrangement.midi_ins.len(),
|
|
||||||
|
|
||||||
outputs_height: arrangement.h_outputs(),
|
outputs_height: arrangement.h_outputs(),
|
||||||
outputs_count: arrangement.midi_outs.len(),
|
|
||||||
|
|
||||||
scenes_height: h_scenes_area,
|
scenes_height: h_scenes_area,
|
||||||
scene_selected: arrangement.selection().scene(),
|
scene_selected: arrangement.selection().scene(),
|
||||||
scene_count: arrangement.scenes.len(),
|
|
||||||
scene_last: arrangement.scenes.len().saturating_sub(1),
|
scene_last: arrangement.scenes.len().saturating_sub(1),
|
||||||
scene_scroll: Fill::y(Fixed::x(1, ScrollbarV {
|
scene_scroll: Fill::y(Fixed::x(1, ScrollbarV {
|
||||||
offset: arrangement.scene_scroll,
|
offset: arrangement.scene_scroll,
|
||||||
|
|
@ -63,7 +54,6 @@ impl<'a> ArrangerView<'a> {
|
||||||
})),
|
})),
|
||||||
|
|
||||||
tracks_height: h_tracks_area,
|
tracks_height: h_tracks_area,
|
||||||
track_count: arrangement.tracks.len(),
|
|
||||||
track_selected: arrangement.selection().track(),
|
track_selected: arrangement.selection().track(),
|
||||||
track_scroll: Fill::x(Fixed::y(1, ScrollbarH {
|
track_scroll: Fill::x(Fixed::y(1, ScrollbarH {
|
||||||
offset: arrangement.track_scroll,
|
offset: arrangement.track_scroll,
|
||||||
|
|
@ -108,9 +98,9 @@ impl<'a> ArrangerView<'a> {
|
||||||
|
|
||||||
/// Render track headers
|
/// Render track headers
|
||||||
pub(crate) fn tracks (&'a self) -> impl Content<TuiOut> + 'a {
|
pub(crate) fn tracks (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
let Self { width_side, width_mid, track_count, track_selected, is_editing, .. } = self;
|
let Self { width_side, width_mid, track_selected, is_editing, .. } = self;
|
||||||
Tryptich::center(3)
|
Tryptich::center(3)
|
||||||
.left(*width_side, button_3("t", "track", format!("{}", *track_count), *is_editing))
|
.left(*width_side, button_3("t", "track", format!("{}", self.arrangement.tracks.len()), *is_editing))
|
||||||
.right(*width_side, button_2("T", "add track", *is_editing))
|
.right(*width_side, button_2("T", "add track", *is_editing))
|
||||||
.middle(*width_mid, per_track(*width_mid, ||self.tracks_with_sizes_scrolled(),
|
.middle(*width_mid, per_track(*width_mid, ||self.tracks_with_sizes_scrolled(),
|
||||||
|index, track|wrap(
|
|index, track|wrap(
|
||||||
|
|
@ -126,7 +116,7 @@ impl<'a> ArrangerView<'a> {
|
||||||
|
|
||||||
/// Render device switches.
|
/// Render device switches.
|
||||||
pub(crate) fn devices (&'a self) -> impl Content<TuiOut> + 'a {
|
pub(crate) fn devices (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
let Self { width_side, width_mid, track_count, track_selected, is_editing, .. } = self;
|
let Self { width_side, width_mid, track_selected, is_editing, .. } = self;
|
||||||
Tryptich::top(1)
|
Tryptich::top(1)
|
||||||
.left(*width_side, button_3("d", "devices", format!("{}", 0), *is_editing))
|
.left(*width_side, button_3("d", "devices", format!("{}", 0), *is_editing))
|
||||||
.right(*width_side, button_2("D", "add device", *is_editing))
|
.right(*width_side, button_2("D", "add device", *is_editing))
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ pub struct MidiEditor {
|
||||||
pub mode: PianoHorizontal,
|
pub mode: PianoHorizontal,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
has!(Measure<TuiOut>: |self: MidiEditor|self.size);
|
||||||
|
|
||||||
impl std::fmt::Debug for MidiEditor {
|
impl std::fmt::Debug for MidiEditor {
|
||||||
fn fmt (&self, f: &mut Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
fn fmt (&self, f: &mut Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
|
||||||
f.debug_struct("MidiEditor")
|
f.debug_struct("MidiEditor")
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
has_size!(<TuiOut>|self: MidiEditor|&self.size);
|
|
||||||
|
|
||||||
content!(TuiOut: |self: MidiEditor| {
|
content!(TuiOut: |self: MidiEditor| {
|
||||||
self.autoscroll();
|
self.autoscroll();
|
||||||
//self.autozoom();
|
//self.autozoom();
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ pub struct PianoHorizontal {
|
||||||
pub keys_width: u16,
|
pub keys_width: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
has!(Measure<TuiOut>:|self:PianoHorizontal|self.size);
|
||||||
|
|
||||||
impl PianoHorizontal {
|
impl PianoHorizontal {
|
||||||
pub fn new (clip: Option<&Arc<RwLock<MidiClip>>>) -> Self {
|
pub fn new (clip: Option<&Arc<RwLock<MidiClip>>>) -> Self {
|
||||||
let size = Measure::new();
|
let size = Measure::new();
|
||||||
|
|
@ -227,8 +229,6 @@ impl PianoHorizontal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
has_size!(<TuiOut>|self:PianoHorizontal|&self.size);
|
|
||||||
|
|
||||||
impl TimeRange for PianoHorizontal {
|
impl TimeRange for PianoHorizontal {
|
||||||
fn time_len (&self) -> &AtomicUsize { self.range.time_len() }
|
fn time_len (&self) -> &AtomicUsize { self.range.time_len() }
|
||||||
fn time_zoom (&self) -> &AtomicUsize { self.range.time_zoom() }
|
fn time_zoom (&self) -> &AtomicUsize { self.range.time_zoom() }
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ pub(crate) use std::path::PathBuf;
|
||||||
pub(crate) use std::error::Error;
|
pub(crate) use std::error::Error;
|
||||||
pub(crate) use std::ffi::OsString;
|
pub(crate) use std::ffi::OsString;
|
||||||
|
|
||||||
pub(crate) use ::tengri::{from, Usually, Perhaps, dsl::*, input::*, output::*, tui::{*, ratatui::prelude::*}};
|
pub(crate) use ::tengri::{from, Usually, Perhaps, Has};
|
||||||
|
pub(crate) use ::tengri::{dsl::*, input::*, output::*, tui::{*, ratatui::prelude::*}};
|
||||||
pub(crate) use ::tek_engine::*;
|
pub(crate) use ::tek_engine::*;
|
||||||
pub(crate) use ::tek_engine::midi::{u7, LiveEvent, MidiMessage};
|
pub(crate) use ::tek_engine::midi::{u7, LiveEvent, MidiMessage};
|
||||||
pub(crate) use ::tek_engine::jack::{Control, ProcessScope, MidiWriter, RawMidi};
|
pub(crate) use ::tek_engine::jack::{Control, ProcessScope, MidiWriter, RawMidi};
|
||||||
|
|
|
||||||
|
|
@ -9,24 +9,19 @@ pub(crate) use std::sync::{Arc, atomic::{AtomicUsize, AtomicBool, Ordering::Rela
|
||||||
pub(crate) use std::fmt::Debug;
|
pub(crate) use std::fmt::Debug;
|
||||||
pub(crate) use std::ops::{Add, Sub, Mul, Div, Rem};
|
pub(crate) use std::ops::{Add, Sub, Mul, Div, Rem};
|
||||||
|
|
||||||
pub(crate) use ::tengri::{from, Usually, Perhaps, tui::*};
|
pub(crate) use ::tengri::{from, Usually, Perhaps, Has, tui::*};
|
||||||
|
|
||||||
pub use ::atomic_float; pub(crate) use atomic_float::*;
|
pub use ::atomic_float; pub(crate) use atomic_float::*;
|
||||||
|
|
||||||
pub trait Has<T>: Send + Sync {
|
//pub trait MaybeHas<T>: Send + Sync {
|
||||||
fn get (&self) -> &T;
|
//fn get (&self) -> Option<&T>;
|
||||||
fn get_mut (&mut self) -> &mut T;
|
//}
|
||||||
}
|
|
||||||
|
|
||||||
pub trait MaybeHas<T>: Send + Sync {
|
//impl<T, U: Has<Option<T>>> MaybeHas<T> for U {
|
||||||
fn get (&self) -> Option<&T>;
|
//fn get (&self) -> Option<&T> {
|
||||||
}
|
//Has::<Option<T>>::get(self).as_ref()
|
||||||
|
//}
|
||||||
impl<T, U: Has<Option<T>>> MaybeHas<T> for U {
|
//}
|
||||||
fn get (&self) -> Option<&T> {
|
|
||||||
Has::<Option<T>>::get(self).as_ref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export] macro_rules! has {
|
#[macro_export] macro_rules! has {
|
||||||
($T:ty: |$self:ident : $S:ty| $x:expr) => {
|
($T:ty: |$self:ident : $S:ty| $x:expr) => {
|
||||||
|
|
|
||||||
2
deps/tengri
vendored
2
deps/tengri
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit a9619ab9cea40aed3ec30483f4a7db03ca7fec9d
|
Subproject commit 8bfd1a23a1f880a1d2fb104a158fc51f244acd6e
|
||||||
Loading…
Add table
Add a link
Reference in a new issue