fixed some bugs with file picker & loading different file types - will start working on brainf##k interpreter tomorrow because a compiler isn't enough.

This commit is contained in:
2025-06-22 05:19:55 +01:00
parent 2b777f55c7
commit 6ea3a76d74
2 changed files with 119 additions and 33 deletions
+116 -28
View File
@@ -1,5 +1,6 @@
use std::{
ffi::OsStr,
fs,
path::{Path, PathBuf},
sync::mpsc::Sender,
};
@@ -147,7 +148,29 @@ impl Editor {
if let Some(path) = &self.path {
// Save to existing path
if let Err(why) = std::fs::write(path, &self.text) {
self.buffer = self.text.clone();
let text = if path.extension().is_some_and(|ext| ext == "dsb") {
let mut res = Vec::new();
for line in self.text.lines() {
for line in line.split_whitespace() {
match u32::from_str_radix(line, 16) {
Ok(num) => res.push(num),
Err(e) => {
self.error = Some(format!("Failed to parse file: {e}"));
return;
}
}
}
}
res.into_iter()
.flat_map(u32::to_be_bytes)
.collect::<Vec<u8>>()
} else {
self.text.as_bytes().to_vec()
};
if let Err(why) = std::fs::write(path, text) {
self.error = Some(format!("Failed to save file: {why}"));
} else {
self.unsaved = false;
@@ -231,15 +254,39 @@ impl Editor {
if let Some(dialog) = &mut self.open_file_dialog {
if dialog.show(ctx).selected() {
if let Some(file) = dialog.path() {
match std::fs::read_to_string(file) {
Ok(content) => {
self.text = content;
self.path = Some(file.to_path_buf());
self.unsaved = false;
self.error = None;
// check if the file is a binary file
if file.extension().is_some_and(|ext| ext == "dsb") {
match std::fs::read(file) {
Ok(content) => {
let mut res = String::new();
for (i, b) in content.iter().enumerate() {
res.push_str(&format!("{b:02x}"));
if i % 4 == 3 {
res.push('\n');
}
}
self.text = res.clone();
self.buffer = res;
self.path = Some(file.to_path_buf());
self.unsaved = false;
self.error = None;
}
Err(e) => {
self.error = Some(format!("Failed to read file: {e}"));
}
}
Err(e) => {
self.error = Some(format!("Failed to read file: {e}"));
} else {
match std::fs::read_to_string(file) {
Ok(content) => {
self.text = content.clone();
self.buffer = content;
self.path = Some(file.to_path_buf());
self.unsaved = false;
self.error = None;
}
Err(e) => {
self.error = Some(format!("Failed to read file: {e}"));
}
}
}
}
@@ -251,7 +298,30 @@ impl Editor {
if let Some(dialog) = &mut self.save_file_dialog {
if dialog.show(ctx).selected() {
if let Some(file) = dialog.path() {
match std::fs::write(file, &self.text) {
self.buffer = self.text.clone();
let content = if file.extension().is_some_and(|ext| ext == "dsb") {
let mut res = Vec::new();
for line in self.text.lines() {
for line in line.split_whitespace() {
match u32::from_str_radix(line, 16) {
Ok(num) => res.push(num),
Err(e) => {
self.error =
Some(format!("Failed to parse file: {e}"));
return;
}
}
}
}
res.into_iter()
.flat_map(u32::to_be_bytes)
.collect::<Vec<u8>>()
} else {
self.text.clone().as_bytes().to_vec()
};
match std::fs::write(file, content) {
Ok(()) => {
self.path = Some(file.to_path_buf());
self.unsaved = false;
@@ -420,6 +490,41 @@ impl Editor {
});
}
fn build(&mut self) {
if let Some(path) = &self.path {
match path.extension().and_then(|ext| ext.to_str()) {
Some("dsa") => {
let mut compiler = CompilerEngine::new();
compiler.start_compilation(path);
// Or block until done
let instructions = match compiler.wait_for_result() {
Ok(instructions) => instructions,
Err(e) => {
self.error = Some(e.to_string());
return;
}
};
self.output = instructions
.iter()
.flat_map(|i| i.encode().to_be_bytes().to_vec())
.collect();
}
Some("dsb") => {
if let Ok(bytes) = fs::read(path) {
self.output = bytes;
} else {
self.error = Some("Failed to read file".to_string());
}
}
_ => {
self.error = Some(format!("Invalid file type: {}", self.filename()));
}
}
}
}
fn render_toolbar(&mut self, _state: &mut State, ui: &mut Ui, ctx: &Context) {
self.handle_file_dialogs(ctx);
@@ -451,24 +556,7 @@ impl Editor {
// builds the current file
if ui.button("Build").clicked() && !self.unsaved {
if let Some(path) = &self.path {
let mut compiler = CompilerEngine::new();
compiler.start_compilation(path);
// Or block until done
let instructions = match compiler.wait_for_result() {
Ok(instructions) => instructions,
Err(e) => {
self.error = Some(e.to_string());
return;
}
};
self.output = instructions
.iter()
.flat_map(|i| i.encode().to_be_bytes().to_vec())
.collect();
}
self.build();
}
// Loads the generated binary into the assembler at the provided offset