chore: run cargo fmt

This commit is contained in:
Stevan Freeborn
2026-01-25 17:26:40 -06:00
parent 2c098b23b7
commit db0cd51818
8 changed files with 355 additions and 348 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
pub mod tabs;
pub mod action_bar;
pub mod editor;
pub mod status_bar;
pub mod action_bar;
pub mod tabs;
+4 -3
View File
@@ -11,8 +11,9 @@ pub fn view<'a>(files: &'a [File], active_index: usize) -> Element<'a, Message>
let is_focused = index == active_index;
let label = text(file.display_name());
let close_btn =
button(text("x")).padding(1).on_press(Message::FileActionSelected(FileAction::Close(Some(index))));
let close_btn = button(text("x"))
.padding(1)
.on_press(Message::FileActionSelected(FileAction::Close(Some(index))));
button(
row![label, close_btn]
@@ -62,7 +63,7 @@ pub fn view<'a>(files: &'a [File], active_index: usize) -> Element<'a, Message>
bottom: 0.0,
}))
.direction(scrollable::Direction::Horizontal(
scrollable::Scrollbar::new().spacing(1)
scrollable::Scrollbar::new().spacing(1),
))
.style(|theme: &Theme, status: scrollable::Status| {
let mut style = scrollable::default(theme, status);
+68 -62
View File
@@ -1,87 +1,93 @@
use std::{ffi, path::{Path, PathBuf}};
use std::{
ffi,
path::{Path, PathBuf},
};
use iced::widget::{markdown, text_editor};
pub struct File {
content: text_editor::Content,
path: Option<PathBuf>,
markdown: Vec<markdown::Item>,
content: text_editor::Content,
path: Option<PathBuf>,
markdown: Vec<markdown::Item>,
}
impl Default for File {
fn default() -> Self {
File {
content: text_editor::Content::new(),
path: None,
markdown: Vec::new(),
}
fn default() -> Self {
File {
content: text_editor::Content::new(),
path: None,
markdown: Vec::new(),
}
}
}
impl File {
pub fn from(content: &str, path: Option<PathBuf>) -> Self {
let text_editor_content = text_editor::Content::with_text(content);
let markdown = markdown::parse(content).collect();
pub fn from(content: &str, path: Option<PathBuf>) -> Self {
let text_editor_content = text_editor::Content::with_text(content);
let markdown = markdown::parse(content).collect();
File {
content: text_editor_content,
path,
markdown,
}
File {
content: text_editor_content,
path,
markdown,
}
}
pub fn content(&self) -> &text_editor::Content {
&self.content
}
pub fn content(&self) -> &text_editor::Content {
&self.content
}
pub fn content_mut(&mut self) -> &mut text_editor::Content {
&mut self.content
}
pub fn content_mut(&mut self) -> &mut text_editor::Content {
&mut self.content
}
pub fn set_content(&mut self, content: &str) {
self.content = text_editor::Content::with_text(content);
}
pub fn set_content(&mut self, content: &str) {
self.content = text_editor::Content::with_text(content);
}
pub fn markdown(&self) -> Vec<&markdown::Item> {
self.markdown.iter().collect()
}
pub fn markdown(&self) -> Vec<&markdown::Item> {
self.markdown.iter().collect()
}
pub fn update_markdown(&mut self) {
self.markdown = markdown::parse(&self.content.text()).collect();
}
pub fn update_markdown(&mut self) {
self.markdown = markdown::parse(&self.content.text()).collect();
}
pub fn path(&self) -> Option<&PathBuf> {
self.path.as_ref()
}
pub fn path(&self) -> Option<&PathBuf> {
self.path.as_ref()
}
pub fn set_path(&mut self, path: Option<PathBuf>) {
self.path = path;
}
pub fn set_path(&mut self, path: Option<PathBuf>) {
self.path = path;
}
pub fn extension(&self) -> Option<&str> {
self.path
.as_deref()
.and_then(Path::extension)
.and_then(ffi::OsStr::to_str)
}
pub fn extension(&self) -> Option<&str> {
self
.path
.as_deref()
.and_then(Path::extension)
.and_then(ffi::OsStr::to_str)
}
pub fn display_name(&self) -> &str {
self.path
.as_deref()
.and_then(|p| p.file_name())
.and_then(|n| n.to_str())
.unwrap_or("New file")
}
pub fn display_name(&self) -> &str {
self
.path
.as_deref()
.and_then(|p| p.file_name())
.and_then(|n| n.to_str())
.unwrap_or("New file")
}
pub fn position_summary(&self) -> String {
let pos = self.content.cursor().position;
format!("Ln {}, Col {}", pos.line, pos.column)
}
pub fn position_summary(&self) -> String {
let pos = self.content.cursor().position;
format!("Ln {}, Col {}", pos.line, pos.column)
}
pub fn path_summary(&self) -> String {
self.path
.as_deref()
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_default()
}
pub fn path_summary(&self) -> String {
self
.path
.as_deref()
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_default()
}
}
+49 -49
View File
@@ -7,75 +7,75 @@ use iced::Task;
use iced::widget::text_editor;
pub fn edit(state: &mut State, action: text_editor::Action) -> Task<Message> {
state.apply_edit(action);
Task::none()
state.apply_edit(action);
Task::none()
}
pub fn switch_tab(state: &mut State, index: usize) -> Task<Message> {
state.switch_tab(index);
Task::none()
state.switch_tab(index);
Task::none()
}
pub fn link_clicked(url: String) -> Task<Message> {
println!("Opening link: {}", url);
Task::none()
println!("Opening link: {}", url);
Task::none()
}
pub fn file_action(state: &mut State, action: FileAction) -> Task<Message> {
match action {
FileAction::New => {
state.new_file();
Task::none()
}
FileAction::Close(index) => {
if state.close_file(index) {
iced::exit()
} else {
Task::none()
}
}
FileAction::Open => Task::perform(io::open_file(), Message::FileOpened),
FileAction::Save => {
let (current_path, content) = state.active_file_data();
let path = current_path.cloned();
Task::perform(io::save_file(path, content), Message::FileSaved)
}
FileAction::SaveAs => {
let (_, content) = state.active_file_data();
Task::perform(io::save_file(None, content), Message::FileSaved)
}
match action {
FileAction::New => {
state.new_file();
Task::none()
}
FileAction::Close(index) => {
if state.close_file(index) {
iced::exit()
} else {
Task::none()
}
}
FileAction::Open => Task::perform(io::open_file(), Message::FileOpened),
FileAction::Save => {
let (current_path, content) = state.active_file_data();
let path = current_path.cloned();
Task::perform(io::save_file(path, content), Message::FileSaved)
}
FileAction::SaveAs => {
let (_, content) = state.active_file_data();
Task::perform(io::save_file(None, content), Message::FileSaved)
}
}
}
pub fn opened_file(state: &mut State, result: Result<(PathBuf, String), String>) -> Task<Message> {
match result {
Ok((path, content)) => {
state.open_file(path, content);
}
Err(_error) => {}
};
match result {
Ok((path, content)) => {
state.open_file(path, content);
}
Err(_error) => {}
};
Task::none()
Task::none()
}
pub fn saved_file(state: &mut State, result: Result<PathBuf, String>) -> Task<Message> {
match result {
Ok(path) => {
state.set_active_file_path(path);
}
Err(_error) => {}
};
match result {
Ok(path) => {
state.set_active_file_path(path);
}
Err(_error) => {}
};
Task::none()
Task::none()
}
pub fn view_action(state: &mut State, action: ViewAction) -> Task<Message> {
match action {
ViewAction::Increase => state.increase_font(),
ViewAction::Decrease => state.decrease_font(),
ViewAction::Reset => state.reset_font(),
ViewAction::TogglePreview => state.toggle_preview(),
}
match action {
ViewAction::Increase => state.increase_font(),
ViewAction::Decrease => state.decrease_font(),
ViewAction::Reset => state.reset_font(),
ViewAction::TogglePreview => state.toggle_preview(),
}
Task::none()
Task::none()
}
+29 -29
View File
@@ -4,42 +4,42 @@ use rfd::AsyncFileDialog;
use tokio::fs;
pub async fn open_file() -> Result<(PathBuf, String), String> {
let handle_result = AsyncFileDialog::new()
.set_directory("/")
.pick_file()
.await
.ok_or(String::from("Dialog cancelled"));
let handle_result = AsyncFileDialog::new()
.set_directory("/")
.pick_file()
.await
.ok_or(String::from("Dialog cancelled"));
match handle_result {
Ok(handle) => {
let path = handle.path().to_owned();
let content_result = fs::read_to_string(&path).await.map_err(|e| e.to_string());
match handle_result {
Ok(handle) => {
let path = handle.path().to_owned();
let content_result = fs::read_to_string(&path).await.map_err(|e| e.to_string());
match content_result {
Ok(content) => Ok((path, content)),
Err(e) => Err(e),
}
}
match content_result {
Ok(content) => Ok((path, content)),
Err(e) => Err(e),
}
}
Err(e) => Err(e),
}
}
pub async fn save_file(path: Option<PathBuf>, text: String) -> Result<PathBuf, String> {
let save_path = match path {
Some(p) => p,
None => AsyncFileDialog::new()
.set_directory("/")
.save_file()
.await
.ok_or(String::from("Dialog cancelled"))?
.path()
.to_owned(),
};
let save_path = match path {
Some(p) => p,
None => AsyncFileDialog::new()
.set_directory("/")
.save_file()
.await
.ok_or(String::from("Dialog cancelled"))?
.path()
.to_owned(),
};
let save_result = fs::write(&save_path, text).await.map_err(|e| e.to_string());
let save_result = fs::write(&save_path, text).await.map_err(|e| e.to_string());
match save_result {
Ok(_) => Ok(save_path),
Err(err) => Err(err),
}
match save_result {
Ok(_) => Ok(save_path),
Err(err) => Err(err),
}
}
+55 -55
View File
@@ -3,66 +3,66 @@ use iced::keyboard::{self, Key, Modifiers};
use crate::message::{FileAction, Message, ViewAction};
pub struct Keybinding {
key: &'static str,
modifiers: Modifiers,
message: Message,
key: &'static str,
modifiers: Modifiers,
message: Message,
}
impl Keybinding {
pub fn should_handle(&self, key_pressed: &Key, modifiers: &Modifiers) -> bool {
let key = keyboard::Key::Character(self.key.into());
modifiers.contains(self.modifiers) && key_pressed == &key
}
pub fn should_handle(&self, key_pressed: &Key, modifiers: &Modifiers) -> bool {
let key = keyboard::Key::Character(self.key.into());
modifiers.contains(self.modifiers) && key_pressed == &key
}
pub fn message(&self) -> Message {
self.message.clone()
}
pub fn message(&self) -> Message {
self.message.clone()
}
}
pub const ALL: &[Keybinding] = &[
Keybinding {
key: "o",
modifiers: Modifiers::CTRL,
message: Message::FileActionSelected(FileAction::Open),
},
Keybinding {
key: "n",
modifiers: Modifiers::CTRL,
message: Message::FileActionSelected(FileAction::New),
},
Keybinding {
key: "s",
modifiers: Modifiers::CTRL.union(Modifiers::SHIFT),
message: Message::FileActionSelected(FileAction::SaveAs),
},
Keybinding {
key: "s",
modifiers: Modifiers::CTRL,
message: Message::FileActionSelected(FileAction::Save),
},
Keybinding {
key: "w",
modifiers: Modifiers::CTRL,
message: Message::FileActionSelected(FileAction::Close(None)),
},
Keybinding {
key: "p",
modifiers: Modifiers::CTRL,
message: Message::ViewActionSelected(ViewAction::TogglePreview),
},
Keybinding {
key: "=",
modifiers: Modifiers::CTRL,
message: Message::ViewActionSelected(ViewAction::Increase),
},
Keybinding {
key: "-",
modifiers: Modifiers::CTRL,
message: Message::ViewActionSelected(ViewAction::Decrease),
},
Keybinding {
key: "0",
modifiers: Modifiers::CTRL,
message: Message::ViewActionSelected(ViewAction::Reset),
},
Keybinding {
key: "o",
modifiers: Modifiers::CTRL,
message: Message::FileActionSelected(FileAction::Open),
},
Keybinding {
key: "n",
modifiers: Modifiers::CTRL,
message: Message::FileActionSelected(FileAction::New),
},
Keybinding {
key: "s",
modifiers: Modifiers::CTRL.union(Modifiers::SHIFT),
message: Message::FileActionSelected(FileAction::SaveAs),
},
Keybinding {
key: "s",
modifiers: Modifiers::CTRL,
message: Message::FileActionSelected(FileAction::Save),
},
Keybinding {
key: "w",
modifiers: Modifiers::CTRL,
message: Message::FileActionSelected(FileAction::Close(None)),
},
Keybinding {
key: "p",
modifiers: Modifiers::CTRL,
message: Message::ViewActionSelected(ViewAction::TogglePreview),
},
Keybinding {
key: "=",
modifiers: Modifiers::CTRL,
message: Message::ViewActionSelected(ViewAction::Increase),
},
Keybinding {
key: "-",
modifiers: Modifiers::CTRL,
message: Message::ViewActionSelected(ViewAction::Decrease),
},
Keybinding {
key: "0",
modifiers: Modifiers::CTRL,
message: Message::ViewActionSelected(ViewAction::Reset),
},
];
+44 -44
View File
@@ -4,70 +4,70 @@ use iced::widget::text_editor;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FileAction {
New,
Save,
SaveAs,
Open,
Close(Option<usize>),
New,
Save,
SaveAs,
Open,
Close(Option<usize>),
}
impl FileAction {
pub const ALL: &'static [FileAction] = &[
FileAction::New,
FileAction::Save,
FileAction::SaveAs,
FileAction::Open,
FileAction::Close(None),
];
pub const ALL: &'static [FileAction] = &[
FileAction::New,
FileAction::Save,
FileAction::SaveAs,
FileAction::Open,
FileAction::Close(None),
];
}
impl Display for FileAction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
FileAction::New => write!(f, "New file"),
FileAction::Save => write!(f, "Save"),
FileAction::SaveAs => write!(f, "Save as... "),
FileAction::Open => write!(f, "Open"),
FileAction::Close(_) => write!(f, "Close"),
}
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
FileAction::New => write!(f, "New file"),
FileAction::Save => write!(f, "Save"),
FileAction::SaveAs => write!(f, "Save as... "),
FileAction::Open => write!(f, "Open"),
FileAction::Close(_) => write!(f, "Close"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ViewAction {
Increase,
Decrease,
Reset,
TogglePreview,
Increase,
Decrease,
Reset,
TogglePreview,
}
impl ViewAction {
pub const ALL: &'static [ViewAction] = &[
ViewAction::Increase,
ViewAction::Decrease,
ViewAction::Reset,
ViewAction::TogglePreview,
];
pub const ALL: &'static [ViewAction] = &[
ViewAction::Increase,
ViewAction::Decrease,
ViewAction::Reset,
ViewAction::TogglePreview,
];
}
impl Display for ViewAction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ViewAction::Decrease => write!(f, "Decrease font"),
ViewAction::Increase => write!(f, "Increase font"),
ViewAction::Reset => write!(f, "Reset font"),
ViewAction::TogglePreview => write!(f, "Toggle preview"),
}
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ViewAction::Decrease => write!(f, "Decrease font"),
ViewAction::Increase => write!(f, "Increase font"),
ViewAction::Reset => write!(f, "Reset font"),
ViewAction::TogglePreview => write!(f, "Toggle preview"),
}
}
}
#[derive(Debug, Clone)]
pub enum Message {
Edit(text_editor::Action),
FileActionSelected(FileAction),
ViewActionSelected(ViewAction),
SwitchTab(usize),
LinkClicked(String),
FileOpened(Result<(PathBuf, String), String>),
FileSaved(Result<PathBuf, String>),
Edit(text_editor::Action),
FileActionSelected(FileAction),
ViewActionSelected(ViewAction),
SwitchTab(usize),
LinkClicked(String),
FileOpened(Result<(PathBuf, String), String>),
FileSaved(Result<PathBuf, String>),
}
+104 -104
View File
@@ -2,146 +2,146 @@ use std::path::PathBuf;
use iced::widget::text_editor;
use crate::{constants, file};
use crate::message::{FileAction, ViewAction};
use crate::{constants, file};
#[derive(Default, Copy, Clone)]
pub enum Mode {
#[default]
Edit,
Preview,
#[default]
Edit,
Preview,
}
#[derive(Default)]
pub struct State {
mode: Mode,
files: Vec<file::File>,
current_file: usize,
editor_font_size: u32,
selected_file_action: Option<FileAction>,
selected_view_action: Option<ViewAction>,
mode: Mode,
files: Vec<file::File>,
current_file: usize,
editor_font_size: u32,
selected_file_action: Option<FileAction>,
selected_view_action: Option<ViewAction>,
}
impl State {
pub fn new() -> Self {
let default_file = file::File::default();
pub fn new() -> Self {
let default_file = file::File::default();
Self {
files: vec![default_file],
current_file: 0,
editor_font_size: constants::DEFAULT_EDITOR_FONT_SIZE,
..Default::default()
}
Self {
files: vec![default_file],
current_file: 0,
editor_font_size: constants::DEFAULT_EDITOR_FONT_SIZE,
..Default::default()
}
}
pub fn apply_edit(&mut self, action: text_editor::Action) {
self.files[self.current_file].content_mut().perform(action);
}
pub fn new_file(&mut self) {
self.files.push(file::File::default());
self.current_file = self.files.len() - 1;
}
pub fn close_file(&mut self, index: Option<usize>) -> bool {
let index = index.unwrap_or(self.current_file);
if self.files.len() <= 1 {
return true;
}
pub fn apply_edit(&mut self, action: text_editor::Action) {
self.files[self.current_file].content_mut().perform(action);
self.files.remove(index);
if self.current_file >= self.files.len() {
self.current_file = self.files.len().saturating_sub(1);
} else if index < self.current_file {
self.current_file -= 1;
}
pub fn new_file(&mut self) {
self.files.push(file::File::default());
self.current_file = self.files.len() - 1;
false
}
pub fn open_file(&mut self, path: PathBuf, content: String) {
if let Some(index) = self.files.iter().position(|f| f.path() == Some(&path)) {
self.files[index].set_content(&content);
self.current_file = index;
return;
}
pub fn close_file(&mut self, index: Option<usize>) -> bool {
let index = index.unwrap_or(self.current_file);
let opened_file = file::File::from(&content, Some(path));
if self.files.len() <= 1 {
return true;
}
self.files.push(opened_file);
self.current_file = self.files.len() - 1;
}
self.files.remove(index);
if self.current_file >= self.files.len() {
self.current_file = self.files.len().saturating_sub(1);
} else if index < self.current_file {
self.current_file -= 1;
}
false
pub fn switch_tab(&mut self, index: usize) {
if index < self.files.len() {
self.current_file = index;
}
}
pub fn open_file(&mut self, path: PathBuf, content: String) {
if let Some(index) = self.files.iter().position(|f| f.path() == Some(&path)) {
self.files[index].set_content(&content);
self.current_file = index;
return;
}
pub fn active_file_data(&self) -> (Option<&PathBuf>, String) {
let file = &self.files[self.current_file];
(file.path(), file.content().text())
}
let opened_file = file::File::from(&content, Some(path));
self.files.push(opened_file);
self.current_file = self.files.len() - 1;
pub fn set_active_file_path(&mut self, path: PathBuf) {
if let Some(file) = self.files.get_mut(self.current_file) {
file.set_path(Some(path));
}
}
pub fn switch_tab(&mut self, index: usize) {
if index < self.files.len() {
self.current_file = index;
}
pub fn increase_font(&mut self) {
if self.editor_font_size < constants::MAX_EDITOR_FONT_SIZE {
self.editor_font_size += 2;
}
}
pub fn active_file_data(&self) -> (Option<&PathBuf>, String) {
let file = &self.files[self.current_file];
(file.path(), file.content().text())
pub fn decrease_font(&mut self) {
if self.editor_font_size > constants::MIN_EDITOR_FONT_SIZE {
self.editor_font_size -= 2;
}
}
pub fn set_active_file_path(&mut self, path: PathBuf) {
if let Some(file) = self.files.get_mut(self.current_file) {
file.set_path(Some(path));
}
}
pub fn reset_font(&mut self) {
self.editor_font_size = constants::DEFAULT_EDITOR_FONT_SIZE;
}
pub fn increase_font(&mut self) {
if self.editor_font_size < constants::MAX_EDITOR_FONT_SIZE {
self.editor_font_size += 2;
}
pub fn toggle_preview(&mut self) {
match self.mode {
Mode::Edit => {
self.files[self.current_file].update_markdown();
self.mode = Mode::Preview;
}
Mode::Preview => self.mode = Mode::Edit,
}
}
pub fn decrease_font(&mut self) {
if self.editor_font_size > constants::MIN_EDITOR_FONT_SIZE {
self.editor_font_size -= 2;
}
}
pub fn files(&self) -> &[file::File] {
&self.files
}
pub fn reset_font(&mut self) {
self.editor_font_size = constants::DEFAULT_EDITOR_FONT_SIZE;
}
pub fn current_file_index(&self) -> usize {
self.current_file
}
pub fn toggle_preview(&mut self) {
match self.mode {
Mode::Edit => {
self.files[self.current_file].update_markdown();
self.mode = Mode::Preview;
}
Mode::Preview => self.mode = Mode::Edit,
}
}
pub fn active_file(&self) -> &file::File {
&self.files[self.current_file]
}
pub fn files(&self) -> &[file::File] {
&self.files
}
pub fn mode(&self) -> Mode {
self.mode
}
pub fn current_file_index(&self) -> usize {
self.current_file
}
pub fn font_size(&self) -> u32 {
self.editor_font_size
}
pub fn active_file(&self) -> &file::File {
&self.files[self.current_file]
}
pub fn selected_file_action(&self) -> Option<FileAction> {
self.selected_file_action
}
pub fn mode(&self) -> Mode {
self.mode
}
pub fn font_size(&self) -> u32 {
self.editor_font_size
}
pub fn selected_file_action(&self) -> Option<FileAction> {
self.selected_file_action
}
pub fn selected_view_action(&self) -> Option<ViewAction> {
self.selected_view_action
}
pub fn selected_view_action(&self) -> Option<ViewAction> {
self.selected_view_action
}
}