refactor: move some things with their appropriate verticals

This commit is contained in:
i do not exist 2026-07-02 07:55:23 +03:00
parent 3b1c31c78d
commit 51faa82d74
9 changed files with 197 additions and 218 deletions

View file

@ -1,11 +1,12 @@
use crate::*;
pub mod audio; pub use self::audio::*;
pub mod audio; #[allow(unused)] pub use self::audio::*;
pub mod bind; pub use self::bind::*;
pub mod cli; pub use self::cli::*;
pub mod config; pub use self::config::*;
pub mod view; pub use self::view::*;
pub mod draw; pub use self::draw::*;
pub mod mode; pub use self::mode::*;
pub mod size; pub use self::size::*;
/// Total application state.
///
@ -81,26 +82,6 @@ impl App {
}
}
pub fn new_shared (
jack: &Jack<'static>, project: Arrangement, config: Config, mode: impl AsRef<str>
) -> Arc<RwLock<Self>> {
Arc::new(RwLock::new(App::new(jack, project, config, ":menu")))
}
pub fn new_shared_run <W: std::io::Write + Send + Sync + 'static> (
exit: &Exit,
output: W,
jack: &Jack<'static>,
project: Arrangement,
config: Config,
mode: impl AsRef<str>
) -> Usually<(Arc<RwLock<Self>>, Task, Task)> {
let state = Self::new_shared(&jack, project, config, mode);
let keyboard = tui_input(exit.as_ref(), &state, Duration::from_millis(100))?;
let terminal = tui_output(exit.as_ref(), &state, Duration::from_millis(10), output)?;
Ok((state, keyboard, terminal))
}
pub fn confirm (&mut self) -> Perhaps<AppCommand> {
Ok(match &self.dialog {
Dialog::Menu(index, items) => {
@ -250,65 +231,24 @@ impl App {
}
}
/// The [Draw] implementation for [App] handles the loaded view,
/// which is defined in terms of [dizzle] DSL.
///
/// If there is an error, the error is displayed. FIXME: overlay it
/// Then, every top-level form of the DSL description is rendered.
impl Draw<Tui> for App {
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
let xywh = to.area().into();
if let Some(e) = self.error.read().unwrap().as_ref() {
to.show(xywh, e.as_ref());
}
for (index, dsl) in self.mode.view.iter().enumerate() {
if let Err(e) = self.interpret(to, dsl) {
*self.error.write().unwrap() = Some(format!("view #{index}: {e}").into());
break;
}
}
Ok(xywh)
}
}
impl HasClipsSize for App {
fn clips_size (&self) -> &Size { &self.project.size_inner }
}
impl HasJack<'static> for App {
fn jack (&self) -> &Jack<'static> { &self.jack }
}
def_command!(AppCommand: |app: App| {
Nop => Ok(None),
Cancel => todo!(), // TODO delegate:
Confirm => app.confirm(),
Inc { axis: ControlAxis } => app.inc(axis),
Dec { axis: ControlAxis } => app.dec(axis),
SetDialog { dialog: Dialog } => {
swap_value(&mut app.dialog, dialog, |dialog|Self::SetDialog { dialog })
},
});
impl_default!(AppCommand: Self::Nop);
impl_has!(Clock: |self: App|self.project.clock);
impl_has!(Vec<MidiInput>: |self: App|self.project.midi_ins);
impl_has!(Vec<MidiOutput>: |self: App|self.project.midi_outs);
impl_has!(Dialog: |self: App|self.dialog);
impl_has!(Jack<'static>: |self: App|self.jack);
impl_has!(Size: |self: App|self.size);
impl_has!(Pool: |self: App|self.pool);
impl_has!(Selection: |self: App|self.project.selection);
impl_as_ref!(Vec<Scene>: |self: App|self.project.as_ref());
impl_as_mut!(Vec<Scene>: |self: App|self.project.as_mut());
impl_as_ref_opt!(MidiEditor: |self: App|self.project.as_ref_opt());
impl_as_mut_opt!(MidiEditor: |self: App|self.project.as_mut_opt());
impl_has_clips!( |self: App|self.pool.clips);
primitive!(u8: try_to_u8);
primitive!(u16: try_to_u16);
primitive!(usize: try_to_usize);
primitive!(isize: try_to_isize);
namespace!(App: Arc<str> { literal = |dsl|Ok(dsl.src()?.map(|x|x.into())); });
namespace!(App: u8 { literal = |dsl|try_to_u8(dsl); });
@ -374,83 +314,52 @@ namespace!(App: Option<usize> { symbol = |app| {
":selected/track" => app.selection().track(),
}; });
namespace!(App: Option<Arc<RwLock<MidiClip>>> {
symbol = |app| {
":selected/clip" => if let Selection::TrackClip { track, scene } = app.selection() {
app.scenes()[*scene].clips[*track].clone()
} else {
None
}
};
});
namespace!(App: Option<Arc<RwLock<MidiClip>>> { symbol = |app| {
":selected/clip" => if let Selection::TrackClip { track, scene } = app.selection() {
app.scenes()[*scene].clips[*track].clone()
} else {
None
}
}; });
impl<'a> Namespace<'a, AppCommand> for App {
symbols!('a |app| -> AppCommand {
"x/inc" => AppCommand::Inc { axis: ControlAxis::X },
"x/dec" => AppCommand::Dec { axis: ControlAxis::X },
"y/inc" => AppCommand::Inc { axis: ControlAxis::Y },
"y/dec" => AppCommand::Dec { axis: ControlAxis::Y },
"confirm" => AppCommand::Confirm,
"cancel" => AppCommand::Cancel,
});
}
impl HasTrackScroll for App {
fn track_scroll (&self) -> usize {
self.project.track_scroll()
pub fn swap_value <T: Clone + PartialEq, U> (
target: &mut T, value: &T, returned: impl Fn(T)->U
) -> Perhaps<U> {
if *target == *value {
Ok(None)
} else {
let mut value = value.clone();
std::mem::swap(target, &mut value);
Ok(Some(returned(value)))
}
}
impl HasSceneScroll for App {
fn scene_scroll (&self) -> usize {
self.project.scene_scroll()
pub fn toggle_bool <U> (
target: &mut bool, value: &Option<bool>, returned: impl Fn(Option<bool>)->U
) -> Perhaps<U> {
let mut value = value.unwrap_or(!*target);
if value == *target {
Ok(None)
} else {
std::mem::swap(target, &mut value);
Ok(Some(returned(Some(value))))
}
}
impl ScenesView for App {
fn w_mid (&self) -> u16 {
(self.size.w() as u16).saturating_sub(self.w_side())
}
fn w_side (&self) -> u16 {
20
}
fn h_scenes (&self) -> u16 {
(self.size.h() as u16).saturating_sub(20)
}
pub fn scan (dir: &PathBuf) -> Usually<(Vec<OsString>, Vec<OsString>)> {
let (mut subdirs, mut files) = std::fs::read_dir(dir)?
.fold((vec!["..".into()], vec![]), |(mut subdirs, mut files), entry|{
let entry = entry.expect("failed to read drectory entry");
let meta = entry.metadata().expect("failed to read entry metadata");
if meta.is_file() {
files.push(entry.file_name());
} else if meta.is_dir() {
subdirs.push(entry.file_name());
}
(subdirs, files)
});
subdirs.sort();
files.sort();
Ok((subdirs, files))
}
//impl_handle!(TuiIn: |self: App, input|{
//let commands = tek_collect_commands(self, input)?;
//let history = tek_execute_commands(self, commands)?;
//self.history.extend(history.into_iter());
//Ok(None)
//});
//fn tek_collect_commands (app: &App, input: &TuiIn) -> Usually<Vec<AppCommand>> {
//let mut commands = vec![];
//for id in app.mode.keys.iter() {
//if let Some(event_map) = app.config.binds.clone().read().unwrap().get(id.as_ref())
//&& let Some(bindings) = event_map.query(input.event()) {
//for binding in bindings {
//for command in binding.commands.iter() {
//if let Some(command) = app.namespace(command)? as Option<AppCommand> {
//commands.push(command)
//}
//}
//}
//}
//}
//Ok(commands)
//}
//fn tek_execute_commands (
//app: &mut App, commands: Vec<AppCommand>
//) -> Usually<Vec<(AppCommand, Option<AppCommand>)>> {
//let mut history = vec![];
//for command in commands.into_iter() {
//let result = command.act(app);
//match result { Err(err) => { history.push((command, None)); return Err(err) }
//Ok(undo) => { history.push((command, undo)); } };
//}
//Ok(history)
//}