use crossterm::terminal as crossterm_terminal;
use log::debug;
use std::path::{Path, PathBuf};
use crate::input_source::InputSource;
use crate::watch::FileWatcher;
use super::layout::{self, Layout};
use super::terminal;
pub(super) struct JumpEntry {
pub path: PathBuf,
pub y_offset: u32,
}
pub(super) struct Session {
pub layout: Layout,
pub input: InputSource,
pub filename: String,
pub watcher: Option<FileWatcher>,
pub jump_stack: Vec<JumpEntry>,
pub scroll_carry: u32,
pub pending_flash: Option<String>,
pub watch: bool,
pub log_buffer: crate::log::LogBuffer,
}
impl Session {
pub(super) fn current_file_path(&self) -> Option<&Path> {
match &self.input {
InputSource::File(p) => Some(p),
InputSource::Stdin(_) => None,
}
}
pub(super) fn update_layout_for_resize(
&mut self,
new_cols: u16,
new_rows: u16,
sidebar_cols: u16,
) -> anyhow::Result<()> {
let new_winsize = crossterm_terminal::window_size()?;
self.layout = layout::compute_layout(
new_cols,
new_rows,
new_winsize.width,
new_winsize.height,
sidebar_cols,
);
terminal::delete_all_images()?;
Ok(())
}
pub(super) fn handle_exit(
&mut self,
exit: super::effect::ExitReason,
scroll_position: u32,
sidebar_cols: u16,
) -> anyhow::Result<bool> {
use super::effect::ExitReason;
match exit {
ExitReason::Quit => return Ok(true),
ExitReason::Resize { new_cols, new_rows } => {
self.scroll_carry = scroll_position;
debug!("resize: rebuilding tiled document and sidebar");
self.update_layout_for_resize(new_cols, new_rows, sidebar_cols)?;
}
ExitReason::Reload => {
self.scroll_carry = scroll_position;
debug!("file changed: reloading document");
terminal::delete_all_images()?;
}
ExitReason::ConfigReload => {
self.scroll_carry = scroll_position;
debug!("config reload requested");
terminal::delete_all_images()?;
}
ExitReason::Navigate { path } => {
if !path.exists() {
self.pending_flash = Some(format!("File not found: {}", path.display()));
terminal::delete_all_images()?;
return Ok(false);
}
if let InputSource::File(cur) = &self.input {
self.jump_stack.push(JumpEntry {
path: cur.clone(),
y_offset: scroll_position,
});
}
let canonical = std::fs::canonicalize(&path).unwrap_or(path);
debug!("navigate: jumping to {}", canonical.display());
self.input = InputSource::File(canonical.clone());
self.filename = self.input.display_name().to_string();
self.scroll_carry = 0;
if self.watch {
self.watcher = Some(FileWatcher::new(&canonical)?);
}
terminal::delete_all_images()?;
}
ExitReason::GoBack => {
let entry = self.jump_stack.pop().expect("GoBack with empty stack");
debug!("go back: returning to {}", entry.path.display());
self.input = InputSource::File(entry.path.clone());
self.filename = self.input.display_name().to_string();
self.scroll_carry = entry.y_offset;
if self.watch {
self.watcher = Some(FileWatcher::new(&entry.path)?);
}
terminal::delete_all_images()?;
}
}
Ok(false)
}
}