Skip to content

Commit

Permalink
Merge pull request #91 from justinpombrio/engine
Browse files Browse the repository at this point in the history
Add Engine and DocSet, use FocusTarget, bump ppp.
  • Loading branch information
e-matteson committed Apr 4, 2024
2 parents 2f2e102 + 2769962 commit c293d27
Show file tree
Hide file tree
Showing 16 changed files with 476 additions and 147 deletions.
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ bit-set = "0.5"
typed-arena = "2.0"
generational-arena = "0.2"
crossterm = "0.27.0"
serde = { version = "1.0", features = ["derive"] }
ron = "0.8.1"
[dependencies.partial-pretty-printer]
git = "https://github.com/justinpombrio/partial-pretty-printer"
version = "0.4.0"
version = "0.5.1"
features = ["serialization"]
[dependencies.no-nonsense-flamegraphs]
version = "0.2.*"
git = "https://github.com/justinpombrio/no-nonsense-flamegraphs"
Expand Down
17 changes: 15 additions & 2 deletions src/engine/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use super::doc_command::{
TextNavCommand, TreeEdCommand, TreeNavCommand,
};
use crate::language::Storage;
use crate::pretty_doc::DocRef;
use crate::tree::{Bookmark, Location, Mode, Node};
use crate::util::{bug_assert, SynlessBug};
use std::collections::HashMap;
Expand Down Expand Up @@ -42,6 +43,7 @@ pub enum DocError {
EmptyClipboard,
}

#[derive(Debug)]
pub struct Doc {
cursor: Location,
recent: Option<UndoGroup>,
Expand All @@ -61,6 +63,18 @@ impl Doc {
}
}

pub fn doc_ref_source<'d>(&self, s: &'d Storage) -> DocRef<'d> {
DocRef::new_source(s, self.cursor, self.cursor.root_node(s))
}

pub fn doc_ref_display<'d>(&self, s: &'d Storage) -> DocRef<'d> {
DocRef::new_display(s, self.cursor, self.cursor.root_node(s))
}

pub fn cursor(&self) -> Location {
self.cursor
}

pub fn mode(&self) -> Mode {
self.cursor.mode()
}
Expand All @@ -78,7 +92,7 @@ impl Doc {
DocCommand::Ed(cmd) => execute_ed(s, cmd, &mut self.cursor)?,
DocCommand::Clipboard(cmd) => execute_clipboard(s, cmd, &mut self.cursor, clipboard)?,
DocCommand::Nav(cmd) => {
execute_nav(s, cmd, &mut self.cursor, &mut self.bookmarks, clipboard)?;
execute_nav(s, cmd, &mut self.cursor, &mut self.bookmarks)?;
Vec::new()
}
};
Expand Down Expand Up @@ -191,7 +205,6 @@ fn execute_nav(
cmd: NavCommand,
cursor: &mut Location,
bookmarks: &mut HashMap<char, Bookmark>,
clipboard: &mut Vec<Node>,
) -> Result<(), DocError> {
match cmd {
NavCommand::Tree(cmd) => execute_tree_nav(s, cmd, cursor),
Expand Down
148 changes: 148 additions & 0 deletions src/engine/doc_set.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
use super::doc::Doc;
use super::Settings;
use crate::language::Storage;
use crate::pretty_doc::DocRef;
use crate::util::SynlessBug;
use partial_pretty_printer as ppp;
use partial_pretty_printer::pane;
use std::collections::HashMap;
use std::path::{Path, PathBuf};

type DocIndex = usize;

/// Label for documents that might be displayed on the screen.
///
/// Sample PaneNotation, and its corresponding DocLabels:
///
/// ```text
/// +----------------------------+
/// | doc1 |*doc2*| doc3 | |
/// +----------------------------+
/// | |
/// | This is the visible doc. |
/// | |
/// +----------------------------+
/// | doc2.rs 27,1 |
/// +----------------------------+
/// |i->insert h->left |
/// |s->save l->right |
/// +----------------------------+
///
/// +----------------------------+
/// | Aux(tab_bar) |
/// +----------------------------+
/// | |
/// | Visible |
/// | |
/// +----------------------------+
/// | Meta(name) Meta(linecol) |
/// +----------------------------+
/// | |
/// | Aux(key_hints) |
/// +----------------------------+
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum DocLabel {
/// The "real" document that the user is viewing and editing.
Visible,
/// An auto-generated doc containing info about the `Visible` doc, for use in a status bar.
Metadata(String),
/// An auto-generated doc used to implement UI elements like menus.
Auxilliary(String),
}

#[derive(Debug)]
pub struct DocSet {
file_path_to_doc: HashMap<PathBuf, DocIndex>,
/// INVARIANT: DocLabel::Visible is always present.
label_to_doc: HashMap<DocLabel, DocIndex>,
/// DocIndex -> Doc
docs: Vec<Doc>,
}

impl DocSet {
pub fn new(starting_doc: Doc) -> DocSet {
let mut doc_set = DocSet {
file_path_to_doc: HashMap::new(),
label_to_doc: HashMap::new(),
docs: Vec::new(),
};
let starting_doc_index = doc_set.insert_doc(starting_doc);
doc_set
.label_to_doc
.insert(DocLabel::Visible, starting_doc_index);
doc_set
}

pub fn visible_doc(&self) -> &Doc {
let doc_index = *self
.label_to_doc
.get(&DocLabel::Visible)
.bug_msg("VisibleDoc not found");
self.docs.get(doc_index).bug()
}

pub fn metadata_doc(&self, name: &str) -> Option<&Doc> {
let doc_index = *self
.label_to_doc
.get(&DocLabel::Metadata(name.to_owned()))?;
Some(self.docs.get(doc_index).bug())
}

pub fn auxilliary_doc(&self, name: &str) -> Option<&Doc> {
let doc_index = *self
.label_to_doc
.get(&DocLabel::Auxilliary(name.to_owned()))?;
Some(self.docs.get(doc_index).bug())
}

pub fn file_doc(&self, file_path: &Path) -> Option<&Doc> {
let doc_index = *self.file_path_to_doc.get(file_path)?;
Some(self.docs.get(doc_index).bug())
}

pub fn get_content<'s>(
&self,
s: &'s Storage,
label: DocLabel,
settings: &Settings,
) -> Option<(DocRef<'s>, pane::PrintingOptions)> {
let meta_and_aux_options = pane::PrintingOptions {
focus_path: vec![],
focus_target: ppp::FocusTarget::Start,
focus_height: 0.0,
width_strategy: pane::WidthStrategy::Full,
set_focus: false,
};

let (doc, opts) = match label {
DocLabel::Visible => {
let doc = self.visible_doc();
let (focus_path, focus_target) = doc.cursor().path_from_root(s);
let options = pane::PrintingOptions {
focus_path,
focus_target,
focus_height: settings.focus_height,
width_strategy: pane::WidthStrategy::NoMoreThan(settings.max_display_width),
set_focus: true,
};
(doc, options)
}
DocLabel::Metadata(name) => {
let doc = self.metadata_doc(&name)?;
(doc, meta_and_aux_options)
}
DocLabel::Auxilliary(name) => {
let doc = self.auxilliary_doc(&name)?;
(doc, meta_and_aux_options)
}
};
Some((doc.doc_ref_display(s), opts))
}

fn insert_doc(&mut self, doc: Doc) -> usize {
let doc_index = self.docs.len();
self.docs.push(doc);
doc_index
}
}
110 changes: 110 additions & 0 deletions src/engine/engine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#![allow(clippy::module_inception)]

use super::doc::Doc;
use super::doc_set::{DocLabel, DocSet};
use super::Settings;
use crate::language::{Language, LanguageError, LanguageSpec, NotationSetSpec, Storage};
use crate::pretty_doc::{DocRef, PrettyDocError};
use crate::style::Style;
use crate::tree::{Bookmark, Node};
use crate::util::SynlessBug;
use partial_pretty_printer as ppp;
use partial_pretty_printer::pane;
use std::path::Path;

// TODO: think about error types
#[derive(thiserror::Error, Debug)]
pub enum EngineError {
#[error("Did not find doc named '{0}'")]
DocNotFound(String),
#[error("{0}")]
PrintingError(#[from] ppp::PrintingError<PrettyDocError>),
#[error("{0}")]
LanguageError(#[from] LanguageError),
}

#[derive(Debug)]
pub struct Engine {
storage: Storage,
doc_set: DocSet,
clipboard: Vec<Node>,
settings: Settings,
}

impl Engine {
pub fn new(settings: Settings) -> Engine {
todo!()
}

/*************
* Languages *
*************/

pub fn add_language(&mut self, language_spec: LanguageSpec) -> Result<(), EngineError> {
self.storage.add_language(language_spec)?;
Ok(())
}

pub fn add_notation(
&mut self,
language_name: &str,
notation: NotationSetSpec,
) -> Result<(), EngineError> {
let lang = self.storage.language(language_name)?;
lang.add_notation(&mut self.storage, notation)?;
Ok(())
}

pub fn set_display_notation(
&mut self,
language_name: &str,
notation_name: &str,
) -> Result<(), EngineError> {
let lang = self.storage.language(language_name)?;
lang.set_display_notation(&mut self.storage, notation_name)?;
Ok(())
}

pub fn set_source_notation(
&mut self,
language_name: &str,
notation_name: &str,
) -> Result<(), EngineError> {
let lang = self.storage.language(language_name)?;
lang.set_source_notation(&mut self.storage, notation_name)?;
Ok(())
}

pub fn unset_source_notation(&mut self, language_name: &str) -> Result<(), EngineError> {
let lang = self.storage.language(language_name)?;
lang.unset_source_notation(&mut self.storage)?;
Ok(())
}

/******************
* Doc Management *
******************/

pub fn make_empty_doc(&mut self, doc_name: &str, language: Language) {
todo!()
}

/************
* Printing *
************/

fn print_source(&self, doc_path: &Path) -> Result<String, EngineError> {
let doc = self
.doc_set
.file_doc(doc_path)
.ok_or_else(|| EngineError::DocNotFound(doc_path.to_string_lossy().into_owned()))?;
let doc_ref = doc.doc_ref_source(&self.storage);
let source = ppp::pretty_print_to_string(doc_ref, self.settings.max_source_width)?;
Ok(source)
}

fn get_content(&self, label: DocLabel) -> Option<(DocRef, pane::PrintingOptions)> {
self.doc_set
.get_content(&self.storage, label, &self.settings)
}
}
21 changes: 21 additions & 0 deletions src/engine/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,23 @@
mod doc;
mod doc_command;
mod doc_set;
mod engine;

use partial_pretty_printer as ppp;

#[derive(Debug, Clone)]
pub struct Settings {
max_source_width: ppp::Width,
max_display_width: ppp::Width,
focus_height: f32,
}

impl Settings {
fn default() -> Settings {
Settings {
max_source_width: 100,
max_display_width: 120,
focus_height: 0.5,
}
}
}
Loading

0 comments on commit c293d27

Please sign in to comment.