Skip to content

Commit

Permalink
feat: add a status bar
Browse files Browse the repository at this point in the history
  • Loading branch information
justinpombrio committed Jun 4, 2024
1 parent a8dd447 commit a8eea4e
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 30 deletions.
4 changes: 2 additions & 2 deletions scripts/init.rhai
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,13 @@ tree_keymap.bind_key("p", "Paste", || s::paste());
tree_keymap.bind_key("P", "PasteSwap", || s::paste_swap());

tree_keymap.bind_key("I", "Insert", || {
s::open_menu("candidate_node_selection");
s::open_menu("candidate_node_selection", "Select node to insert");
let construct = s::block();
s::insert_node(construct);
});

tree_keymap.bind_key("i", "QuickInsert", || {
s::open_menu("char_node_selection");
s::open_menu("char_node_selection", "Select node to insert");
let construct = s::block();
s::insert_node(construct);
});
Expand Down
2 changes: 1 addition & 1 deletion src/engine/doc_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl fmt::Display for DocName {
use DocName::*;

match self {
File(path) => write!(f, "file:{}", path.to_string_lossy()),
File(path) => write!(f, "{}", path.to_string_lossy()),
Metadata(name) => write!(f, "metadata:{}", name),
Auxilliary(name) => write!(f, "auxilliary:{}", name),
}
Expand Down
9 changes: 8 additions & 1 deletion src/engine/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::Settings;
use crate::language::{Language, LanguageSpec, NotationSetSpec, Storage};
use crate::parsing::{Parse, ParseError};
use crate::pretty_doc::DocRef;
use crate::tree::Node;
use crate::tree::{Mode, Node};
use crate::util::{error, SynlessBug, SynlessError};
use partial_pretty_printer as ppp;
use partial_pretty_printer::pane;
Expand Down Expand Up @@ -198,6 +198,13 @@ impl Engine {
self.doc_set.get_doc_mut(doc_name)
}

pub fn mode(&self) -> Mode {
self.doc_set
.visible_doc()
.map(|doc| doc.mode())
.unwrap_or(Mode::Tree)
}

/****************************
* Doc Loading and Printing *
****************************/
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ pub use engine::{DocName, Engine, Settings};
pub use frontends::Terminal;
pub use keymap::{KeyProg, Keymap, Layer};
pub use language::{
AritySpec, Construct, ConstructSpec, GrammarSpec, LanguageSpec, NotationSetSpec, SortSpec,
Storage,
AritySpec, Construct, ConstructSpec, GrammarSpec, Language, LanguageSpec, NotationSetSpec,
SortSpec, Storage,
};
pub use pretty_doc::DocRef;
pub use runtime::Runtime;
Expand Down
122 changes: 98 additions & 24 deletions src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ const MENU_NAME_LABEL: &str = "menu_name";
const MODE_LABEL: &str = "mode";
const FILENAME_LABEL: &str = "filename";
const SIBLING_INDEX_LABEL: &str = "sibling_index";
const ERROR_LABEL: &str = "error";

const KEYHINTS_PANE_WIDTH: usize = 15;

pub struct Runtime<F: Frontend<Style = Style>> {
engine: Engine,
pane_notation: pane::PaneNotation<DocDisplayLabel, Style>,
default_pane_notation: pane::PaneNotation<DocDisplayLabel, Style>,
menu_pane_notation: pane::PaneNotation<DocDisplayLabel, Style>,
frontend: F,
layers: LayerManager,
}
Expand All @@ -40,7 +42,8 @@ impl<F: Frontend<Style = Style> + 'static> Runtime<F> {

Runtime {
engine,
pane_notation: make_pane_notation(false),
default_pane_notation: make_pane_notation(false),
menu_pane_notation: make_pane_notation(true),
frontend,
layers: LayerManager::new(),
}
Expand Down Expand Up @@ -144,12 +147,12 @@ impl<F: Frontend<Style = Style> + 'static> Runtime<F> {
.map_err(|err| error!(Frontend, "{}", err))?;

let get_content = |doc_label| self.engine.get_content(doc_label);
pane::display_pane(
&mut self.frontend,
&self.pane_notation,
&Style::default(),
&get_content,
)?;
let note = if self.layers.has_open_menu() {
&self.menu_pane_notation
} else {
&self.default_pane_notation
};
pane::display_pane(&mut self.frontend, note, &Style::default(), &get_content)?;

self.frontend
.end_frame()
Expand All @@ -161,6 +164,9 @@ impl<F: Frontend<Style = Style> + 'static> Runtime<F> {
self.make_keyhint_doc(),
self.make_candidate_selection_doc(),
self.make_menu_name_doc(),
self.make_mode_doc(),
self.make_filename_doc(),
self.make_sibling_index_doc(),
] {
let _ = self.engine.delete_doc(&name);
if let Some(node) = node {
Expand All @@ -180,11 +186,7 @@ impl<F: Frontend<Style = Style> + 'static> Runtime<F> {

fn make_keyhint_doc(&mut self) -> (DocName, Option<Node>) {
let visible_doc_name = self.engine.visible_doc_name().cloned();
let mode = if let Some(doc) = self.engine.visible_doc() {
doc.mode()
} else {
Mode::Tree
};
let mode = self.engine.mode();
let storage = self.engine.raw_storage_mut();
let node = self
.layers
Expand All @@ -200,6 +202,43 @@ impl<F: Frontend<Style = Style> + 'static> Runtime<F> {
(DocName::Auxilliary(MENU_NAME_LABEL.to_owned()), opt_node)
}

fn make_mode_doc(&mut self) -> (DocName, Option<Node>) {
let mode = match self.engine.mode() {
Mode::Tree => "TREE".to_owned(),
Mode::Text => "TEXT".to_owned(),
};
let node = self.engine.make_string_doc(mode);
(DocName::Auxilliary(MODE_LABEL.to_owned()), Some(node))
}

fn make_filename_doc(&mut self) -> (DocName, Option<Node>) {
let opt_doc_name = self.engine.visible_doc_name();
let opt_label = opt_doc_name.map(|doc_name| match doc_name {
DocName::File(path) => {
let os_str = path.file_name().unwrap_or_else(|| path.as_os_str());
os_str.to_string_lossy().into_owned()
}
DocName::Metadata(label) => format!("metadata:{}", label),
DocName::Auxilliary(label) => format!("auxilliary:{}", label),
});
let opt_node = opt_label.map(|label| self.engine.make_string_doc(label));
(DocName::Auxilliary(FILENAME_LABEL.to_owned()), opt_node)
}

fn make_sibling_index_doc(&mut self) -> (DocName, Option<Node>) {
let opt_label = self.engine.visible_doc().map(|doc| {
let cursor = doc.cursor();
let s = self.engine.raw_storage();
let (numerator, denominator) = cursor.sibling_index_info(s);
format!("sibling {}/{}", numerator, denominator)
});
let opt_node = opt_label.map(|label| self.engine.make_string_doc(label));
(
DocName::Auxilliary(SIBLING_INDEX_LABEL.to_owned()),
opt_node,
)
}

/******************
* Doc Management *
******************/
Expand Down Expand Up @@ -382,14 +421,19 @@ impl<F: Frontend<Style = Style> + 'static> Runtime<F> {
* Pane Notations *
******************/

fn make_pane_notation(_include_menu: bool) -> pane::PaneNotation<DocDisplayLabel, Style> {
fn make_pane_notation(include_menu: bool) -> pane::PaneNotation<DocDisplayLabel, Style> {
use crate::style::{Base16Color, Priority};
use pane::{PaneNotation, PaneSize};

let bar_style = Style::default()
.with_bg(Base16Color::Base04, Priority::Low)
.with_fg(Base16Color::Base00, Priority::Low)
.with_bold(true, Priority::Low);
let status_bar_style = Style::default()
.with_bg(Base16Color::Base06, Priority::Low)
.with_fg(Base16Color::Base00, Priority::Low)
.with_bold(true, Priority::Low);

let divider = PaneNotation::Style {
style: bar_style.clone(),
notation: Box::new(PaneNotation::Fill { ch: ' ' }),
Expand All @@ -415,23 +459,53 @@ fn make_pane_notation(_include_menu: bool) -> pane::PaneNotation<DocDisplayLabel
label: DocDisplayLabel::Auxilliary(MENU_NAME_LABEL.to_owned()),
};
let menu_bar = PaneNotation::Style {
style: bar_style,
style: bar_style.clone(),
notation: Box::new(PaneNotation::Horz(vec![
(PaneSize::Dynamic, menu_name),
(PaneSize::Proportional(1), padding.clone()),
])),
};

let main_doc_and_menu = PaneNotation::Vert(vec![
(PaneSize::Proportional(1), main_doc),
(PaneSize::Fixed(1), menu_bar),
(PaneSize::Dynamic, menu_doc),
]);
let mode_doc = PaneNotation::Doc {
label: DocDisplayLabel::Auxilliary(MODE_LABEL.to_owned()),
};
let filename_doc = PaneNotation::Doc {
label: DocDisplayLabel::Auxilliary(FILENAME_LABEL.to_owned()),
};
let sibling_index_doc = PaneNotation::Doc {
label: DocDisplayLabel::Auxilliary(SIBLING_INDEX_LABEL.to_owned()),
};
let status_bar = PaneNotation::Style {
style: status_bar_style,
notation: Box::new(PaneNotation::Horz(vec![
(PaneSize::Dynamic, mode_doc),
(PaneSize::Fixed(1), padding.clone()),
(PaneSize::Dynamic, filename_doc),
(PaneSize::Proportional(1), padding.clone()),
(PaneSize::Dynamic, sibling_index_doc),
(PaneSize::Fixed(1), padding),
])),
};

PaneNotation::Horz(vec![
(PaneSize::Proportional(1), main_doc_and_menu),
(PaneSize::Fixed(1), divider),
(PaneSize::Fixed(KEYHINTS_PANE_WIDTH), keyhints),
let mut main_doc_and_menu = vec![(PaneSize::Proportional(1), main_doc)];
if include_menu {
main_doc_and_menu.push((PaneSize::Fixed(1), menu_bar));
main_doc_and_menu.push((PaneSize::Dynamic, menu_doc));
}

PaneNotation::Vert(vec![
(
PaneSize::Proportional(1),
PaneNotation::Horz(vec![
(
PaneSize::Proportional(1),
PaneNotation::Vert(main_doc_and_menu),
),
(PaneSize::Fixed(1), divider),
(PaneSize::Fixed(KEYHINTS_PANE_WIDTH), keyhints),
]),
),
(PaneSize::Fixed(1), status_bar),
])
}

Expand Down
9 changes: 9 additions & 0 deletions src/tree/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@ impl Location {
(path_from_root, target)
}

/// Return the _one-indexed_ sibling index and number of siblings of this location. Being in
/// text is treated the same as being at the texty node.
pub fn sibling_index_info(self, s: &Storage) -> (usize, usize) {
match self.0 {
InText(node, _) | AtNode(node) => (node.sibling_index(s) + 1, node.num_siblings(s)),
BelowNode(node) => (0, node.num_children(s).bug()),
}
}

/**************
* Navigation *
**************/
Expand Down

0 comments on commit a8eea4e

Please sign in to comment.