Lines
96.43 %
Functions
50 %
Branches
100 %
//! Focusable sub-pane model.
//!
//! Each view declares a static list of its panes; one is always focused.
//! Focus is stored by value so reads never need to index.
#[cfg(test)]
mod tests;
/// Named pane within a view.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PaneId {
/// The nomiscript input prompt line.
Prompt,
/// The scrollback transcript.
Scrollback,
}
/// A view's focusable sub-panes with exactly one always focused.
///
/// The pane list is `'static` (declared per view); focus is stored by value
/// so reads never need to index.
#[derive(Debug)]
pub struct PaneSet {
panes: &'static [PaneId],
focused: PaneId,
impl PaneSet {
/// Construct a `PaneSet` with the given static pane list and initial focus.
pub const fn new(panes: &'static [PaneId], initial: PaneId) -> Self {
Self {
panes,
focused: initial,
/// The currently focused pane.
pub fn focused(&self) -> PaneId {
self.focused
/// Whether `id` is currently focused.
pub fn is_focused(&self, id: PaneId) -> bool {
self.focused == id
/// Move focus to `id`. A no-op if `id` is not in the pane list.
pub fn focus(&mut self, id: PaneId) {
if self.panes.contains(&id) {
self.focused = id;
/// Cycle focus forward or backward through the pane list, wrapping at
/// both ends.
pub fn cycle(&mut self, forward: bool) {
if let Some(i) = self.panes.iter().position(|p| *p == self.focused) {
let len = self.panes.len();
let next = if forward {
(i + 1) % len
} else {
(i + len - 1) % len
};
if let Some(p) = self.panes.get(next) {
self.focused = *p;