use {
reovim_driver_command::{
ArgKind, ArgSpec, Command, CommandContext, CommandHandler, CommandResult,
},
reovim_driver_layout::{NavigateDirection, SplitDirection},
reovim_driver_session::{CompositorApi, SessionRuntime},
reovim_kernel::api::v1::CommandId,
};
use crate::ids;
#[derive(Debug, Clone, Copy, Default)]
pub struct FocusLeft;
impl Command for FocusLeft {
fn id(&self) -> CommandId {
ids::FOCUS_LEFT
}
fn description(&self) -> &'static str {
"Move focus to left window"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for FocusLeft {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.navigate(NavigateDirection::Left) {
Ok(window) => match runtime.focus(window) {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
},
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct FocusDown;
impl Command for FocusDown {
fn id(&self) -> CommandId {
ids::FOCUS_DOWN
}
fn description(&self) -> &'static str {
"Move focus to window below"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for FocusDown {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.navigate(NavigateDirection::Down) {
Ok(window) => match runtime.focus(window) {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
},
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct FocusUp;
impl Command for FocusUp {
fn id(&self) -> CommandId {
ids::FOCUS_UP
}
fn description(&self) -> &'static str {
"Move focus to window above"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for FocusUp {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.navigate(NavigateDirection::Up) {
Ok(window) => match runtime.focus(window) {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
},
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct FocusRight;
impl Command for FocusRight {
fn id(&self) -> CommandId {
ids::FOCUS_RIGHT
}
fn description(&self) -> &'static str {
"Move focus to right window"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for FocusRight {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.navigate(NavigateDirection::Right) {
Ok(window) => match runtime.focus(window) {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
},
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct FocusNext;
impl Command for FocusNext {
fn id(&self) -> CommandId {
ids::FOCUS_NEXT
}
fn description(&self) -> &'static str {
"Cycle focus to next window"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for FocusNext {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.cycle(true) {
Ok(window) => match runtime.focus(window) {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
},
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct FocusPrev;
impl Command for FocusPrev {
fn id(&self) -> CommandId {
ids::FOCUS_PREV
}
fn description(&self) -> &'static str {
"Cycle focus to previous window"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for FocusPrev {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.cycle(false) {
Ok(window) => match runtime.focus(window) {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
},
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct SplitHorizontal;
impl Command for SplitHorizontal {
fn id(&self) -> CommandId {
ids::SPLIT_HORIZONTAL
}
fn description(&self) -> &'static str {
"Split window horizontally"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
impl CommandHandler for SplitHorizontal {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.split(SplitDirection::Horizontal) {
Ok(_new_window) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct SplitVertical;
impl Command for SplitVertical {
fn id(&self) -> CommandId {
ids::SPLIT_VERTICAL
}
fn description(&self) -> &'static str {
"Split window vertically"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
impl CommandHandler for SplitVertical {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.split(SplitDirection::Vertical) {
Ok(_new_window) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct CloseWindow;
impl Command for CloseWindow {
fn id(&self) -> CommandId {
ids::CLOSE_WINDOW
}
fn description(&self) -> &'static str {
"Close current window"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
impl CommandHandler for CloseWindow {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.close_current_window() {
Ok(_neighbor) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct CloseOthers;
impl Command for CloseOthers {
fn id(&self) -> CommandId {
ids::CLOSE_OTHERS
}
fn description(&self) -> &'static str {
"Close all other windows"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
impl CommandHandler for CloseOthers {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.close_others() {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct SplitNew;
impl Command for SplitNew {
fn id(&self) -> CommandId {
ids::SPLIT_NEW
}
fn description(&self) -> &'static str {
"Create new window with empty buffer"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
impl CommandHandler for SplitNew {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.split(SplitDirection::Vertical) {
Ok(_new_window) => {
CommandResult::Success
}
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
const RESIZE_DELTA: i16 = 1;
#[derive(Debug, Clone, Copy, Default)]
pub struct ResizeHeightIncrease;
impl Command for ResizeHeightIncrease {
fn id(&self) -> CommandId {
ids::RESIZE_HEIGHT_INCREASE
}
fn description(&self) -> &'static str {
"Increase window height"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
impl CommandHandler for ResizeHeightIncrease {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.resize(NavigateDirection::Down, RESIZE_DELTA) {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ResizeHeightDecrease;
impl Command for ResizeHeightDecrease {
fn id(&self) -> CommandId {
ids::RESIZE_HEIGHT_DECREASE
}
fn description(&self) -> &'static str {
"Decrease window height"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
impl CommandHandler for ResizeHeightDecrease {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.resize(NavigateDirection::Down, -RESIZE_DELTA) {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ResizeWidthIncrease;
impl Command for ResizeWidthIncrease {
fn id(&self) -> CommandId {
ids::RESIZE_WIDTH_INCREASE
}
fn description(&self) -> &'static str {
"Increase window width"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
impl CommandHandler for ResizeWidthIncrease {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.resize(NavigateDirection::Right, RESIZE_DELTA) {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ResizeWidthDecrease;
impl Command for ResizeWidthDecrease {
fn id(&self) -> CommandId {
ids::RESIZE_WIDTH_DECREASE
}
fn description(&self) -> &'static str {
"Decrease window width"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
impl CommandHandler for ResizeWidthDecrease {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.resize(NavigateDirection::Right, -RESIZE_DELTA) {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ResizeEqual;
impl Command for ResizeEqual {
fn id(&self) -> CommandId {
ids::RESIZE_EQUAL
}
fn description(&self) -> &'static str {
"Equalize all window sizes"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
impl CommandHandler for ResizeEqual {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.equalize() {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ToggleFloat;
impl Command for ToggleFloat {
fn id(&self) -> CommandId {
ids::TOGGLE_FLOAT
}
fn description(&self) -> &'static str {
"Toggle window between tiled and floating"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
impl CommandHandler for ToggleFloat {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.toggle_float() {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct RaiseFloat;
impl Command for RaiseFloat {
fn id(&self) -> CommandId {
ids::RAISE_FLOAT
}
fn description(&self) -> &'static str {
"Raise floating window to front"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
impl CommandHandler for RaiseFloat {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.raise_float() {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct LowerFloat;
impl Command for LowerFloat {
fn id(&self) -> CommandId {
ids::LOWER_FLOAT
}
fn description(&self) -> &'static str {
"Lower floating window to back"
}
fn args(&self) -> Vec<ArgSpec> {
Vec::new()
}
}
impl CommandHandler for LowerFloat {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.lower_float() {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct LayerOpacitySet;
impl Command for LayerOpacitySet {
fn id(&self) -> CommandId {
ids::LAYER_OPACITY_SET
}
fn description(&self) -> &'static str {
"Set layer opacity (0-100)"
}
fn args(&self) -> Vec<ArgSpec> {
vec![ArgSpec::required(
"percentage",
ArgKind::Count,
"Opacity percentage (0-100)",
)]
}
fn names(&self) -> &[&'static str] {
&["LayerOpacity"]
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for LayerOpacitySet {
fn execute(&self, runtime: &mut SessionRuntime<'_>, ctx: &CommandContext) -> CommandResult {
let pct = ctx.count().unwrap_or(100);
#[allow(clippy::cast_precision_loss)]
let opacity = (pct as f32 / 100.0).clamp(0.0, 1.0);
match runtime.set_active_layer_opacity(opacity) {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct LayerOpacityIncrease;
impl Command for LayerOpacityIncrease {
fn id(&self) -> CommandId {
ids::LAYER_OPACITY_INCREASE
}
fn description(&self) -> &'static str {
"Increase layer opacity by 10%"
}
fn names(&self) -> &[&'static str] {
&["LayerOpacityUp"]
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for LayerOpacityIncrease {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.adjust_active_layer_opacity(0.1) {
Ok(_) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct LayerOpacityDecrease;
impl Command for LayerOpacityDecrease {
fn id(&self) -> CommandId {
ids::LAYER_OPACITY_DECREASE
}
fn description(&self) -> &'static str {
"Decrease layer opacity by 10%"
}
fn names(&self) -> &[&'static str] {
&["LayerOpacityDown"]
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for LayerOpacityDecrease {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.adjust_active_layer_opacity(-0.1) {
Ok(_) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct TabNew;
impl Command for TabNew {
fn id(&self) -> CommandId {
ids::TAB_NEW
}
fn description(&self) -> &'static str {
"Create a new tab page"
}
fn names(&self) -> &[&'static str] {
&["tabnew"]
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for TabNew {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.tab_new() {
Ok(_) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct TabClose;
impl Command for TabClose {
fn id(&self) -> CommandId {
ids::TAB_CLOSE
}
fn description(&self) -> &'static str {
"Close the current tab page"
}
fn names(&self) -> &[&'static str] {
&["tabclose", "tabc"]
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for TabClose {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.tab_close() {
Ok(()) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct TabNext;
impl Command for TabNext {
fn id(&self) -> CommandId {
ids::TAB_NEXT
}
fn description(&self) -> &'static str {
"Switch to the next tab page"
}
fn names(&self) -> &[&'static str] {
&["tabnext", "tabn"]
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for TabNext {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.tab_next() {
Ok(_) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct TabPrev;
impl Command for TabPrev {
fn id(&self) -> CommandId {
ids::TAB_PREV
}
fn description(&self) -> &'static str {
"Switch to the previous tab page"
}
fn names(&self) -> &[&'static str] {
&["tabprev", "tabp"]
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for TabPrev {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.tab_prev() {
Ok(_) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct TabGoto;
impl Command for TabGoto {
fn id(&self) -> CommandId {
ids::TAB_GOTO
}
fn description(&self) -> &'static str {
"Switch to tab page by index"
}
fn args(&self) -> Vec<ArgSpec> {
vec![ArgSpec::required(
"index",
ArgKind::Count,
"Tab index (1-based)",
)]
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for TabGoto {
fn execute(&self, runtime: &mut SessionRuntime<'_>, ctx: &CommandContext) -> CommandResult {
let index = ctx.count().unwrap_or(1);
match runtime.tab_goto(index.saturating_sub(1)) {
Ok(_) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct MoveToNewTab;
impl Command for MoveToNewTab {
fn id(&self) -> CommandId {
ids::MOVE_TO_NEW_TAB
}
fn description(&self) -> &'static str {
"Move current window to new tab"
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
impl CommandHandler for MoveToNewTab {
fn execute(&self, runtime: &mut SessionRuntime<'_>, _ctx: &CommandContext) -> CommandResult {
match runtime.tab_new() {
Ok(_) => CommandResult::Success,
Err(e) => CommandResult::Error(e.to_string()),
}
}
}
#[must_use]
pub fn all_commands() -> Vec<Box<dyn CommandHandler>> {
vec![
Box::new(FocusLeft),
Box::new(FocusDown),
Box::new(FocusUp),
Box::new(FocusRight),
Box::new(FocusNext),
Box::new(FocusPrev),
Box::new(SplitHorizontal),
Box::new(SplitVertical),
Box::new(SplitNew),
Box::new(CloseWindow),
Box::new(CloseOthers),
Box::new(ResizeHeightIncrease),
Box::new(ResizeHeightDecrease),
Box::new(ResizeWidthIncrease),
Box::new(ResizeWidthDecrease),
Box::new(ResizeEqual),
Box::new(ToggleFloat),
Box::new(RaiseFloat),
Box::new(LowerFloat),
Box::new(LayerOpacitySet),
Box::new(LayerOpacityIncrease),
Box::new(LayerOpacityDecrease),
Box::new(TabNew),
Box::new(TabClose),
Box::new(TabNext),
Box::new(TabPrev),
Box::new(TabGoto),
Box::new(MoveToNewTab),
]
}
#[cfg(test)]
#[path = "command_tests.rs"]
mod tests;