terminal checkpoint before async
This commit is contained in:
parent
0d38cd53fa
commit
ec1b855686
|
@ -26,3 +26,9 @@ Added indent recognition (when there is a line break, the indentation level is k
|
|||
Added testing
|
||||
Added Ctrl+T : turn 4 spaces into tab across the whole document
|
||||
Added Time debug
|
||||
Added Tree toggle for performance
|
||||
Added Alt+Arrows to move through tabs
|
||||
Added Zoom
|
||||
Added cd
|
||||
Added terminal color
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"tabs":["/home/penwing/Documents/notes/victory2.txt"],"theme":6}
|
||||
{"tabs":["/home/penwing/Documents/notes/victory2.txt","/home/penwing/Documents/projects/rust/calcifer/src/calcifer/code_editor/themes/sonokai.rs"],"theme":4}
|
|
@ -3,6 +3,7 @@ use egui::{text::CCursor, text_edit::CCursorRange};
|
|||
use std::{env, path::Path, path::PathBuf, cmp::max, io, fs, cmp::min};
|
||||
use crate::tools;
|
||||
use crate::TIME_LABELS;
|
||||
use crate::PATH_ROOT;
|
||||
|
||||
pub mod code_editor;
|
||||
use code_editor::CodeEditor;
|
||||
|
@ -16,6 +17,13 @@ impl super::Calcifer {
|
|||
.resizable(false)
|
||||
.show(ctx, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.add(egui::Button::new("open file")).clicked() {
|
||||
if let Some(path) = rfd::FileDialog::new().set_directory(Path::new(&PATH_ROOT)).pick_file() {
|
||||
self.selected_tab = self.open_file(&path);
|
||||
}
|
||||
}
|
||||
ui.separator();
|
||||
|
||||
ui.label("Theme ");
|
||||
egui::ComboBox::from_label("")
|
||||
.selected_text(format!("{}", self.theme.name))
|
||||
|
@ -28,7 +36,9 @@ impl super::Calcifer {
|
|||
});
|
||||
|
||||
ui.separator();
|
||||
ui.checkbox(&mut self.debug_display, "Debug display");
|
||||
self.tree_display = self.toggle(ui, self.tree_display, "Tree");
|
||||
ui.separator();
|
||||
self.debug_display = self.toggle(ui, self.debug_display, "Debug");
|
||||
ui.separator();
|
||||
|
||||
if self.debug_display {
|
||||
|
@ -44,15 +54,13 @@ impl super::Calcifer {
|
|||
}
|
||||
|
||||
pub fn draw_tree_panel(&mut self, ctx: &egui::Context) {
|
||||
if !self.tree_display {
|
||||
return
|
||||
}
|
||||
egui::SidePanel::left("file_tree_panel").show(ctx, |ui| {
|
||||
ui.heading("Bookshelf");
|
||||
if ui.add(egui::Button::new("open file")).clicked() {
|
||||
if let Some(path) = rfd::FileDialog::new().pick_file() {
|
||||
self.selected_tab = self.open_file(&path);
|
||||
}
|
||||
}
|
||||
ui.separator();
|
||||
let _ = self.list_files(ui, Path::new("/home/penwing/Documents/"));
|
||||
let _ = self.list_files(ui, Path::new(&PATH_ROOT));
|
||||
ui.separator();
|
||||
});
|
||||
}
|
||||
|
@ -63,11 +71,15 @@ impl super::Calcifer {
|
|||
.min_height(0.0)
|
||||
.show(ctx, |ui| {
|
||||
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
|
||||
let command_color = egui::Color32::from_hex(self.theme.functions).expect("Theme color issue (functions)");
|
||||
let entry_color = egui::Color32::from_hex(self.theme.literals).expect("Theme color issue (literals)");
|
||||
let bg_color = egui::Color32::from_hex(self.theme.bg).expect("Theme color issue (bg)");
|
||||
|
||||
ui.label("");
|
||||
ui.horizontal(|ui| {
|
||||
ui.style_mut().visuals.extreme_bg_color = egui::Color32::from_hex(self.theme.bg).expect("Could not convert color");
|
||||
ui.style_mut().visuals.extreme_bg_color = bg_color;
|
||||
let Self { command, .. } = self;
|
||||
ui.label(format!("{}>", env::current_dir().expect("Could not find Shell Environnment").file_name().expect("Could not get Shell Environnment Name").to_string_lossy().to_string()));
|
||||
ui.colored_label(command_color.clone(), tools::format_path(&env::current_dir().expect("Could not find Shell Environnment"), 2));
|
||||
let response = ui.add(egui::TextEdit::singleline(command).desired_width(f32::INFINITY).lock_focus(true));
|
||||
|
||||
if response.lost_focus() && ctx.input(|i| i.key_pressed(egui::Key::Enter)) {
|
||||
|
@ -83,10 +95,10 @@ impl super::Calcifer {
|
|||
ui.horizontal_wrapped(|ui| {
|
||||
ui.spacing_mut().item_spacing.y = 0.0;
|
||||
for entry in &self.command_history {
|
||||
ui.label(format!("{}> {}", entry.env, entry.command));
|
||||
ui.colored_label(command_color, format!("{}> {}", entry.env, entry.command));
|
||||
ui.end_row();
|
||||
if entry.output != "" {
|
||||
ui.label(&entry.output);
|
||||
ui.colored_label(entry_color, &entry.output);
|
||||
ui.end_row();
|
||||
}
|
||||
if entry.error != "" {
|
||||
|
@ -138,9 +150,16 @@ impl super::Calcifer {
|
|||
pub fn draw_content_panel(&mut self, ctx: &egui::Context) {
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.add(egui::Button::new("open in terminal")).clicked() {
|
||||
let mut path = self.tabs[self.selected_tab.to_index()].path.clone();
|
||||
path.pop();
|
||||
tools::run_command(format!("cd {}", path.display()));
|
||||
}
|
||||
|
||||
ui.label("Picked file:");
|
||||
ui.monospace(self.tabs[self.selected_tab.to_index()].path.to_string_lossy().to_string());
|
||||
});
|
||||
ui.separator();
|
||||
|
||||
if self.selected_tab == tools::TabNumber::None {
|
||||
return
|
||||
|
@ -165,7 +184,7 @@ impl super::Calcifer {
|
|||
|
||||
CodeEditor::default().id_source("code editor")
|
||||
.with_rows(max(45,lines))
|
||||
.with_fontsize(14.0)
|
||||
.with_fontsize(self.font_size)
|
||||
.with_theme(self.theme)
|
||||
.with_syntax(tools::to_syntax(¤t_tab.language))
|
||||
.with_numlines(true)
|
||||
|
@ -249,6 +268,15 @@ impl super::Calcifer {
|
|||
current_tab.code = current_tab.code.replace(" ", "\t")
|
||||
}
|
||||
|
||||
pub fn move_through_tabs(&mut self, forward : bool) {
|
||||
let new_index = if forward {
|
||||
(self.selected_tab.to_index() + 1) % self.tabs.len()
|
||||
} else {
|
||||
self.selected_tab.to_index().checked_sub(1).unwrap_or(self.tabs.len() - 1)
|
||||
};
|
||||
self.selected_tab = tools::TabNumber::from_index(new_index);
|
||||
}
|
||||
|
||||
fn list_files(&mut self, ui: &mut egui::Ui, path: &Path) -> io::Result<()> {
|
||||
if let Some(name) = path.file_name() {
|
||||
if path.is_dir() {
|
||||
|
@ -300,4 +328,17 @@ impl super::Calcifer {
|
|||
self.tabs.remove(index);
|
||||
return tools::TabNumber::from_index(min(index, self.tabs.len() - 1))
|
||||
}
|
||||
|
||||
fn toggle(&self, ui: &mut egui::Ui, display : bool, title : &str) -> bool {
|
||||
let text = if display.clone() {
|
||||
format!("hide {}", title)
|
||||
} else {
|
||||
format!("show {}", title)
|
||||
};
|
||||
|
||||
if ui.add(egui::Button::new(text)).clicked() {
|
||||
return !display
|
||||
}
|
||||
return display
|
||||
}
|
||||
}
|
||||
|
|
1
src/calcifer_save.json
Normal file
1
src/calcifer_save.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"tabs":["/home/penwing/Documents/notes/victory2.txt","/home/penwing/Documents/projects/rust/calcifer/src/calcifer/code_editor/themes/sonokai.rs"],"theme":6}
|
31
src/main.rs
31
src/main.rs
|
@ -13,6 +13,7 @@ const RED : egui::Color32 = egui::Color32::from_rgb(235, 108, 99);
|
|||
const SAVE_PATH : &str = "calcifer_save.json";
|
||||
const TIME_LABELS : [&str; 5] = ["settings", "tree", "terminal", "tabs", "content"];
|
||||
const MAX_FPS : f32 = 30.0;
|
||||
const PATH_ROOT : &str = "/home/penwing/Documents/";
|
||||
|
||||
|
||||
fn main() -> Result<(), eframe::Error> {
|
||||
|
@ -55,6 +56,7 @@ struct Calcifer {
|
|||
command_history: Vec<tools::CommandEntry>,
|
||||
|
||||
theme: ColorTheme,
|
||||
font_size: f32,
|
||||
|
||||
search: tools::search::SearchWindow,
|
||||
searching: bool,
|
||||
|
@ -62,6 +64,8 @@ struct Calcifer {
|
|||
debug_display: bool,
|
||||
time_watch: Vec<f32>,
|
||||
next_frame: time::Instant,
|
||||
|
||||
tree_display: bool,
|
||||
}
|
||||
|
||||
|
||||
|
@ -75,6 +79,7 @@ impl Default for Calcifer {
|
|||
command_history: Vec::new(),
|
||||
|
||||
theme: DEFAULT_THEMES[0],
|
||||
font_size: 14.0,
|
||||
|
||||
search: tools::search::SearchWindow::default(),
|
||||
searching: false,
|
||||
|
@ -82,6 +87,8 @@ impl Default for Calcifer {
|
|||
debug_display: false,
|
||||
time_watch: vec![0.0; TIME_LABELS.len()],
|
||||
next_frame: time::Instant::now(),
|
||||
|
||||
tree_display: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,18 +101,34 @@ impl eframe::App for Calcifer {
|
|||
|
||||
let mut watch = time::Instant::now();
|
||||
|
||||
if ctx.input( |i| i.key_pressed(egui::Key::S) && i.modifiers.ctrl) {
|
||||
self.handle_save_file(self.save_tab());
|
||||
}
|
||||
|
||||
if ctx.input( |i| i.key_pressed(egui::Key::T) && i.modifiers.ctrl) {
|
||||
self.indent_with_tabs();
|
||||
}
|
||||
|
||||
if ctx.input( |i| i.key_pressed(egui::Key::S) && i.modifiers.ctrl) {
|
||||
self.handle_save_file(self.save_tab());
|
||||
}
|
||||
|
||||
if ctx.input( |i| i.key_pressed(egui::Key::S) && i.modifiers.ctrl && i.modifiers.shift) {
|
||||
self.handle_save_file(self.save_tab_as());
|
||||
}
|
||||
|
||||
if ctx.input( |i| i.key_pressed(egui::Key::ArrowLeft) && i.modifiers.alt) {
|
||||
self.move_through_tabs(false);
|
||||
}
|
||||
|
||||
if ctx.input( |i| i.key_pressed(egui::Key::ArrowRight) && i.modifiers.alt) {
|
||||
self.move_through_tabs(true);
|
||||
}
|
||||
|
||||
if ctx.input( |i| i.zoom_delta() > 1.0) {
|
||||
self.font_size = (self.font_size * 1.1).min(30.0);
|
||||
}
|
||||
|
||||
if ctx.input( |i| i.zoom_delta() < 1.0) {
|
||||
self.font_size = (self.font_size / 1.1).max(10.0);
|
||||
}
|
||||
|
||||
if ctx.input( |i| i.key_pressed(egui::Key::F) && i.modifiers.ctrl) {
|
||||
self.searching = !self.searching.clone();
|
||||
if self.searching {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{process::Command, cmp::Ordering, env, path::PathBuf, fs::read_to_string, fs::write};
|
||||
use std::{env, process::Command, cmp::Ordering, path::PathBuf, path::Path, fs::read_to_string, fs::write, path::Component, ffi::OsStr};
|
||||
use crate::calcifer::code_editor::Syntax;
|
||||
use eframe::egui;
|
||||
use egui::text_edit::CCursorRange;
|
||||
|
@ -179,6 +179,17 @@ pub fn to_syntax(language : &str) -> Syntax {
|
|||
|
||||
pub fn run_command(cmd : String) -> CommandEntry {
|
||||
let mut entry = CommandEntry::default();
|
||||
if &cmd[..2] == "cd" {
|
||||
let path_append = cmd[3..].replace("~", "/home/penwing");
|
||||
let path = Path::new(&path_append);
|
||||
entry.command = cmd;
|
||||
|
||||
if format!("{}", path.display()) != "/" {
|
||||
if !env::set_current_dir(path).is_ok() {
|
||||
entry.error = format!("Could not find path : {}", path.display());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let output = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(cmd.clone())
|
||||
|
@ -188,6 +199,7 @@ pub fn run_command(cmd : String) -> CommandEntry {
|
|||
entry.command = cmd;
|
||||
entry.output = (&String::from_utf8_lossy(&output.stdout)).to_string();
|
||||
entry.error = (&String::from_utf8_lossy(&output.stderr)).to_string();
|
||||
}
|
||||
|
||||
entry
|
||||
}
|
||||
|
@ -209,5 +221,20 @@ pub fn sort_directories_first(a: &std::fs::DirEntry, b: &std::fs::DirEntry) -> O
|
|||
}
|
||||
|
||||
|
||||
pub fn format_path(path: &Path, n_parents: usize) -> String {
|
||||
let components: Vec<&OsStr> = path
|
||||
.components()
|
||||
.rev()
|
||||
.take(n_parents + 1) // Take up to three components (root, parent, file/folder)
|
||||
.filter_map(|component| match component {
|
||||
Component::RootDir | Component::CurDir => None,
|
||||
_ => Some(component.as_os_str()),
|
||||
})
|
||||
.collect();
|
||||
|
||||
format!("{}>", components.iter().rev().map(|&c| c.to_string_lossy()).collect::<Vec<_>>().join("/"))
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
|
@ -227,10 +227,9 @@ impl SearchWindow {
|
|||
self.search(tabs, selected_tab);
|
||||
}
|
||||
|
||||
println!("trying to replace {} with {}", self.search_text, self.replace_text);
|
||||
|
||||
for element in &self.results {
|
||||
tabs[element.tab.to_index()].code = tabs[element.tab.to_index()].code.replace(&self.search_text, &self.replace_text);
|
||||
tabs[element.tab.to_index()].saved = false;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue