From 209cce96a5f3ce7c8c1d98367b639d939c38e334 Mon Sep 17 00:00:00 2001 From: Brooks J Rady Date: Tue, 12 Jan 2021 04:34:19 +0000 Subject: [PATCH] Finish implementing default layouts --- assets/layouts/default.yaml | 2 +- assets/layouts/strider.yaml | 4 +- assets/plugins/status-bar.wasm | Bin 412277 -> 412266 bytes src/input.rs | 4 +- src/layout.rs | 5 + src/main.rs | 290 +++++++++++++++++---------------- 6 files changed, 159 insertions(+), 146 deletions(-) diff --git a/assets/layouts/default.yaml b/assets/layouts/default.yaml index 8c87e635..e6335691 100644 --- a/assets/layouts/default.yaml +++ b/assets/layouts/default.yaml @@ -5,4 +5,4 @@ parts: - direction: Vertical split_size: Fixed: 1 - plugin: status-bar.wasm \ No newline at end of file + plugin: status-bar \ No newline at end of file diff --git a/assets/layouts/strider.yaml b/assets/layouts/strider.yaml index 40dde92b..e33f516a 100644 --- a/assets/layouts/strider.yaml +++ b/assets/layouts/strider.yaml @@ -6,9 +6,9 @@ parts: - direction: Horizontal split_size: Percent: 20 - plugin: strider.wasm + plugin: strider - direction: Horizontal - direction: Vertical split_size: Fixed: 1 - plugin: status-bar.wasm \ No newline at end of file + plugin: status-bar \ No newline at end of file diff --git a/assets/plugins/status-bar.wasm b/assets/plugins/status-bar.wasm index d434bc1d19963bfa5272982047dc03115e3b36f0..57b00f2be83ef116bf0992b598dd04e57470f508 100644 GIT binary patch delta 18549 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 delta 18733 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 diff --git a/src/input.rs b/src/input.rs index c921bdfd..3c5518f8 100644 --- a/src/input.rs +++ b/src/input.rs @@ -317,8 +317,8 @@ pub fn get_help(mode: &InputMode) -> Vec { " Quit".into(), " Scroll".into(), "<1> New Tab".into(), - "<2> Next Tab".into(), - "<3> Last Tab".into(), + "<2/3> Move Tab".into(), + "<4> Close Tab".into(), ]; match mode { InputMode::Normal => vec![" Command Mode".into()], diff --git a/src/layout.rs b/src/layout.rs index 193de93a..2935d42d 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -1,3 +1,4 @@ +use directories_next::ProjectDirs; use serde::{Deserialize, Serialize}; use std::{fs::File, io::prelude::*, path::PathBuf}; @@ -179,7 +180,11 @@ pub struct Layout { impl Layout { pub fn new(layout_path: PathBuf) -> Self { + let project_dirs = ProjectDirs::from("org", "Mosaic Contributors", "Mosaic").unwrap(); + let layout_dir = project_dirs.data_dir().join("layouts/"); let mut layout_file = File::open(&layout_path) + .or_else(|_| File::open(&layout_path.with_extension("yaml"))) + .or_else(|_| File::open(&layout_dir.join(&layout_path).with_extension("yaml"))) .unwrap_or_else(|_| panic!("cannot find layout {}", &layout_path.display())); let mut layout = String::new(); diff --git a/src/main.rs b/src/main.rs index bf39d7f8..27e97766 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,14 +16,15 @@ mod utils; mod wasm_vm; -use std::collections::HashMap; use std::io::Write; use std::os::unix::net::UnixStream; use std::path::PathBuf; use std::sync::mpsc::{channel, sync_channel, Receiver, SendError, Sender, SyncSender}; use std::thread; use std::{cell::RefCell, sync::mpsc::TrySendError}; +use std::{collections::HashMap, fs}; +use directories_next::ProjectDirs; use input::InputMode; use panes::PaneId; use serde::{Deserialize, Serialize}; @@ -208,7 +209,12 @@ pub fn start(mut os_input: Box, opts: CliArgs) { os_input.clone(), opts.debug, ); - let maybe_layout = opts.layout.map(Layout::new); + // Don't use default layouts in tests, but do everywhere else + #[cfg(not(test))] + let default_layout = Some(PathBuf::from("default")); + #[cfg(test)] + let default_layout = None; + let maybe_layout = opts.layout.or(default_layout).map(Layout::new); #[cfg(not(test))] std::panic::set_hook({ @@ -224,64 +230,57 @@ pub fn start(mut os_input: Box, opts: CliArgs) { .name("pty".to_string()) .spawn({ let mut command_is_executing = command_is_executing.clone(); - move || { - if let Some(layout) = maybe_layout { - pty_bus.spawn_terminals_for_layout(layout); - } else { - let pid = pty_bus.spawn_terminal(None); - pty_bus - .send_screen_instructions - .send(ScreenInstruction::NewTab(pid)) - .unwrap(); - } - - loop { - let (event, mut err_ctx) = pty_bus - .receive_pty_instructions - .recv() - .expect("failed to receive event on channel"); - err_ctx.add_call(ContextType::Pty(PtyContext::from(&event))); - pty_bus.send_screen_instructions.update(err_ctx); - match event { - PtyInstruction::SpawnTerminal(file_to_open) => { - let pid = pty_bus.spawn_terminal(file_to_open); - pty_bus - .send_screen_instructions - .send(ScreenInstruction::NewPane(PaneId::Terminal(pid))) - .unwrap(); - } - PtyInstruction::SpawnTerminalVertically(file_to_open) => { - let pid = pty_bus.spawn_terminal(file_to_open); - pty_bus - .send_screen_instructions - .send(ScreenInstruction::VerticalSplit(PaneId::Terminal(pid))) - .unwrap(); - } - PtyInstruction::SpawnTerminalHorizontally(file_to_open) => { - let pid = pty_bus.spawn_terminal(file_to_open); - pty_bus - .send_screen_instructions - .send(ScreenInstruction::HorizontalSplit(PaneId::Terminal(pid))) - .unwrap(); - } - PtyInstruction::NewTab => { + send_pty_instructions.send(PtyInstruction::NewTab).unwrap(); + move || loop { + let (event, mut err_ctx) = pty_bus + .receive_pty_instructions + .recv() + .expect("failed to receive event on channel"); + err_ctx.add_call(ContextType::Pty(PtyContext::from(&event))); + pty_bus.send_screen_instructions.update(err_ctx); + match event { + PtyInstruction::SpawnTerminal(file_to_open) => { + let pid = pty_bus.spawn_terminal(file_to_open); + pty_bus + .send_screen_instructions + .send(ScreenInstruction::NewPane(PaneId::Terminal(pid))) + .unwrap(); + } + PtyInstruction::SpawnTerminalVertically(file_to_open) => { + let pid = pty_bus.spawn_terminal(file_to_open); + pty_bus + .send_screen_instructions + .send(ScreenInstruction::VerticalSplit(PaneId::Terminal(pid))) + .unwrap(); + } + PtyInstruction::SpawnTerminalHorizontally(file_to_open) => { + let pid = pty_bus.spawn_terminal(file_to_open); + pty_bus + .send_screen_instructions + .send(ScreenInstruction::HorizontalSplit(PaneId::Terminal(pid))) + .unwrap(); + } + PtyInstruction::NewTab => { + if let Some(layout) = maybe_layout.clone() { + pty_bus.spawn_terminals_for_layout(layout); + } else { let pid = pty_bus.spawn_terminal(None); pty_bus .send_screen_instructions .send(ScreenInstruction::NewTab(pid)) .unwrap(); } - PtyInstruction::ClosePane(id) => { - pty_bus.close_pane(id); - command_is_executing.done_closing_pane(); - } - PtyInstruction::CloseTab(ids) => { - pty_bus.close_tab(ids); - command_is_executing.done_closing_pane(); - } - PtyInstruction::Quit => { - break; - } + } + PtyInstruction::ClosePane(id) => { + pty_bus.close_pane(id); + command_is_executing.done_closing_pane(); + } + PtyInstruction::CloseTab(ids) => { + pty_bus.close_tab(ids); + command_is_executing.done_closing_pane(); + } + PtyInstruction::Quit => { + break; } } } @@ -421,7 +420,8 @@ pub fn start(mut os_input: Box, opts: CliArgs) { ScreenInstruction::SwitchTabPrev => screen.switch_tab_prev(), ScreenInstruction::CloseTab => screen.close_tab(), ScreenInstruction::ApplyLayout((layout, new_pane_pids)) => { - screen.apply_layout(layout, new_pane_pids) + screen.apply_layout(layout, new_pane_pids); + command_is_executing.done_opening_new_pane(); } ScreenInstruction::Quit => { break; @@ -441,114 +441,122 @@ pub fn start(mut os_input: Box, opts: CliArgs) { let mut send_screen_instructions = send_screen_instructions.clone(); let mut send_app_instructions = send_app_instructions.clone(); - move || { - let store = Store::default(); + let store = Store::default(); + let mut plugin_id = 0; + let mut plugin_map = HashMap::new(); - let mut plugin_id = 0; - let mut plugin_map = HashMap::new(); + move || loop { + let (event, mut err_ctx) = receive_plugin_instructions + .recv() + .expect("failed to receive event on channel"); + err_ctx.add_call(ContextType::Plugin(PluginContext::from(&event))); + send_screen_instructions.update(err_ctx); + send_pty_instructions.update(err_ctx); + send_app_instructions.update(err_ctx); + match event { + PluginInstruction::Load(pid_tx, path) => { + let project_dirs = + ProjectDirs::from("org", "Mosaic Contributors", "Mosaic").unwrap(); + let plugin_dir = project_dirs.data_dir().join("plugins/"); + let wasm_bytes = fs::read(&path) + .or_else(|_| fs::read(&path.with_extension("wasm"))) + .or_else(|_| { + fs::read(&plugin_dir.join(&path).with_extension("wasm")) + }) + .unwrap_or_else(|_| { + panic!("cannot find plugin {}", &path.display()) + }); - loop { - let (event, mut err_ctx) = receive_plugin_instructions - .recv() - .expect("failed to receive event on channel"); - err_ctx.add_call(ContextType::Plugin(PluginContext::from(&event))); - send_screen_instructions.update(err_ctx); - send_pty_instructions.update(err_ctx); - send_app_instructions.update(err_ctx); - match event { - PluginInstruction::Load(pid_tx, path) => { - // FIXME: Cache this compiled module on disk. I could use `(de)serialize_to_file()` for that - let module = Module::from_file(&store, &path).unwrap(); + // FIXME: Cache this compiled module on disk. I could use `(de)serialize_to_file()` for that + let module = Module::new(&store, &wasm_bytes).unwrap(); - let output = Pipe::new(); - let input = Pipe::new(); - let mut wasi_env = WasiState::new("mosaic") - .env("CLICOLOR_FORCE", "1") - .preopen(|p| { - p.directory(".") // FIXME: Change this to a more meaningful dir - .alias(".") - .read(true) - .write(true) - .create(true) - }) - .unwrap() - .stdin(Box::new(input)) - .stdout(Box::new(output)) - .finalize() - .unwrap(); + let output = Pipe::new(); + let input = Pipe::new(); + let mut wasi_env = WasiState::new("mosaic") + .env("CLICOLOR_FORCE", "1") + .preopen(|p| { + p.directory(".") // FIXME: Change this to a more meaningful dir + .alias(".") + .read(true) + .write(true) + .create(true) + }) + .unwrap() + .stdin(Box::new(input)) + .stdout(Box::new(output)) + .finalize() + .unwrap(); - let wasi = wasi_env.import_object(&module).unwrap(); + let wasi = wasi_env.import_object(&module).unwrap(); - let plugin_env = PluginEnv { - plugin_id, - send_pty_instructions: send_pty_instructions.clone(), - send_screen_instructions: send_screen_instructions.clone(), - send_app_instructions: send_app_instructions.clone(), - wasi_env, - }; + let plugin_env = PluginEnv { + plugin_id, + send_pty_instructions: send_pty_instructions.clone(), + send_screen_instructions: send_screen_instructions.clone(), + send_app_instructions: send_app_instructions.clone(), + wasi_env, + }; - let mosaic = mosaic_imports(&store, &plugin_env); - let instance = - Instance::new(&module, &mosaic.chain_back(wasi)).unwrap(); + let mosaic = mosaic_imports(&store, &plugin_env); + let instance = + Instance::new(&module, &mosaic.chain_back(wasi)).unwrap(); - let start = instance.exports.get_function("_start").unwrap(); + let start = instance.exports.get_function("_start").unwrap(); - // This eventually calls the `.init()` method - start.call(&[]).unwrap(); + // This eventually calls the `.init()` method + start.call(&[]).unwrap(); - plugin_map.insert(plugin_id, (instance, plugin_env)); - pid_tx.send(plugin_id).unwrap(); - plugin_id += 1; + plugin_map.insert(plugin_id, (instance, plugin_env)); + pid_tx.send(plugin_id).unwrap(); + plugin_id += 1; + } + PluginInstruction::Draw(buf_tx, pid, rows, cols) => { + let (instance, plugin_env) = plugin_map.get(&pid).unwrap(); + + let draw = instance.exports.get_function("draw").unwrap(); + + draw.call(&[Value::I32(rows as i32), Value::I32(cols as i32)]) + .unwrap(); + + buf_tx.send(wasi_stdout(&plugin_env.wasi_env)).unwrap(); + } + // FIXME: Deduplicate this with the callback below! + PluginInstruction::Input(pid, input_bytes) => { + let (instance, plugin_env) = plugin_map.get(&pid).unwrap(); + + let handle_key = instance.exports.get_function("handle_key").unwrap(); + for key in input_bytes.keys() { + if let Ok(key) = key { + wasi_write_string( + &plugin_env.wasi_env, + &serde_json::to_string(&key).unwrap(), + ); + handle_key.call(&[]).unwrap(); + } } - PluginInstruction::Draw(buf_tx, pid, rows, cols) => { - let (instance, plugin_env) = plugin_map.get(&pid).unwrap(); - let draw = instance.exports.get_function("draw").unwrap(); - - draw.call(&[Value::I32(rows as i32), Value::I32(cols as i32)]) - .unwrap(); - - buf_tx.send(wasi_stdout(&plugin_env.wasi_env)).unwrap(); - } - // FIXME: Deduplicate this with the callback below! - PluginInstruction::Input(pid, input_bytes) => { - let (instance, plugin_env) = plugin_map.get(&pid).unwrap(); - - let handle_key = - instance.exports.get_function("handle_key").unwrap(); + drop(send_screen_instructions.send(ScreenInstruction::Render)); + } + PluginInstruction::GlobalInput(input_bytes) => { + // FIXME: Set up an event subscription system, and timed callbacks + for (instance, plugin_env) in plugin_map.values() { + let handler = + instance.exports.get_function("handle_global_key").unwrap(); for key in input_bytes.keys() { if let Ok(key) = key { wasi_write_string( &plugin_env.wasi_env, &serde_json::to_string(&key).unwrap(), ); - handle_key.call(&[]).unwrap(); + handler.call(&[]).unwrap(); } } - - drop(send_screen_instructions.send(ScreenInstruction::Render)); } - PluginInstruction::GlobalInput(input_bytes) => { - // FIXME: Set up an event subscription system, and timed callbacks - for (instance, plugin_env) in plugin_map.values() { - let handler = - instance.exports.get_function("handle_global_key").unwrap(); - for key in input_bytes.keys() { - if let Ok(key) = key { - wasi_write_string( - &plugin_env.wasi_env, - &serde_json::to_string(&key).unwrap(), - ); - handler.call(&[]).unwrap(); - } - } - } - drop(send_screen_instructions.send(ScreenInstruction::Render)); - } - PluginInstruction::Unload(pid) => drop(plugin_map.remove(&pid)), - PluginInstruction::Quit => break, + drop(send_screen_instructions.send(ScreenInstruction::Render)); } + PluginInstruction::Unload(pid) => drop(plugin_map.remove(&pid)), + PluginInstruction::Quit => break, } } })