colors #6
@ -12,3 +12,5 @@ rfd = "0.15.4"
|
|||||||
toml = "0.9.2"
|
toml = "0.9.2"
|
||||||
dirs = "6.0"
|
dirs = "6.0"
|
||||||
libc = "0.2.174"
|
libc = "0.2.174"
|
||||||
|
syntect = "5.2.0"
|
||||||
|
plist = "1.7.4"
|
||||||
|
|||||||
@ -46,6 +46,7 @@ theme = "System"
|
|||||||
line_side = false
|
line_side = false
|
||||||
font_family = "Monospace"
|
font_family = "Monospace"
|
||||||
font_size = 16.0
|
font_size = 16.0
|
||||||
|
syntax_highlighting = true
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
@ -55,6 +56,7 @@ font_size = 16.0
|
|||||||
| `auto_hide_toolbar` | `false` | If `true`, the menu bar at the top will be hidden. Move your mouse to the top of the window to reveal it. |
|
| `auto_hide_toolbar` | `false` | If `true`, the menu bar at the top will be hidden. Move your mouse to the top of the window to reveal it. |
|
||||||
| `hide_tab_bar` | 'true' | If `false`, a separate tab bar will be drawn below the toolbar. |
|
| `hide_tab_bar` | 'true' | If `false`, a separate tab bar will be drawn below the toolbar. |
|
||||||
| `show_line_numbers` | `false` | If `true`, line numbers will be displayed on the side specified by `line_side`. |
|
| `show_line_numbers` | `false` | If `true`, line numbers will be displayed on the side specified by `line_side`. |
|
||||||
|
| `syntax_highlighting` | `false` | If `true`, text will be highlighted based on detected language. |
|
||||||
| `line_side` | `false` | If `false`, line numbers are on the left. If `true`, they are on the right. |
|
| `line_side` | `false` | If `false`, line numbers are on the left. If `true`, they are on the right. |
|
||||||
| `word_wrap` | `false` | If `true`, lines will wrap when they reach the edge of the window. |
|
| `word_wrap` | `false` | If `true`, lines will wrap when they reach the edge of the window. |
|
||||||
| `font_family` | `"Proportional"` | The font family used for the editor text. |
|
| `font_family` | `"Proportional"` | The font family used for the editor text. |
|
||||||
@ -65,9 +67,8 @@ font_size = 16.0
|
|||||||
In order of importance.
|
In order of importance.
|
||||||
| Feature | Info |
|
| Feature | Info |
|
||||||
| ------- | ---- |
|
| ------- | ---- |
|
||||||
| **Find/Replace:** | Functioning. |
|
|
||||||
| **State/Cache:** | A toggleable option to keep an application state and prevent "Quit without saving" warnings. |
|
| **State/Cache:** | A toggleable option to keep an application state and prevent "Quit without saving" warnings. |
|
||||||
| **Syntax Highlighting/LSP:** | Looking at allowing you to use/attach your own tools for this. |
|
| **LSP:** | Looking at allowing you to use/attach your own tools for this. |
|
||||||
| **Choose Font** | More than just Monospace/Proportional. |
|
| **Choose Font** | More than just Monospace/Proportional. |
|
||||||
| **Vim Mode:** | It's in-escapable. |
|
| **Vim Mode:** | It's in-escapable. |
|
||||||
| **CLI Mode:** | 💀 |
|
| **CLI Mode:** | 💀 |
|
||||||
|
|||||||
111
src/app/theme.rs
111
src/app/theme.rs
@ -1,5 +1,7 @@
|
|||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use egui_extras::syntax_highlighting::CodeTheme;
|
use plist::{Dictionary, Value};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use syntect::highlighting::{Theme as SyntectTheme, ThemeSet, ThemeSettings, Color as SyntectColor, UnderlineOption};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize, Default)]
|
||||||
pub enum Theme {
|
pub enum Theme {
|
||||||
@ -196,11 +198,108 @@ fn detect_system_dark_mode() -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_code_theme_from_visuals(visuals: &egui::Visuals, font_size: f32) -> CodeTheme {
|
fn egui_color_to_syntect(color: egui::Color32) -> SyntectColor {
|
||||||
if visuals.dark_mode {
|
SyntectColor {
|
||||||
CodeTheme::dark(font_size)
|
r: color.r(),
|
||||||
} else {
|
g: color.g(),
|
||||||
CodeTheme::light(font_size)
|
b: color.b(),
|
||||||
|
a: color.a(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_code_theme_from_visuals(visuals: &egui::Visuals, font_size: f32) -> ThemeSet {
|
||||||
|
let text_color = visuals.override_text_color.unwrap_or(visuals.text_color());
|
||||||
|
let bg_color = visuals.extreme_bg_color;
|
||||||
|
let selection_color = visuals.selection.bg_fill;
|
||||||
|
let comment_color = blend_colors(text_color, bg_color, 0.6);
|
||||||
|
let keyword_color = if visuals.dark_mode {
|
||||||
|
blend_colors(egui::Color32::from_rgb(100, 149, 237), text_color, 0.8) // CornflowerBlue-like
|
||||||
|
} else {
|
||||||
|
blend_colors(egui::Color32::from_rgb(0, 0, 139), text_color, 0.8) // DarkBlue-like
|
||||||
|
};
|
||||||
|
let string_color = if visuals.dark_mode {
|
||||||
|
blend_colors(egui::Color32::from_rgb(144, 238, 144), text_color, 0.8) // LightGreen-like
|
||||||
|
} else {
|
||||||
|
blend_colors(egui::Color32::from_rgb(0, 128, 0), text_color, 0.8) // Green-like
|
||||||
|
};
|
||||||
|
let number_color = if visuals.dark_mode {
|
||||||
|
blend_colors(egui::Color32::from_rgb(255, 165, 0), text_color, 0.8) // Orange-like
|
||||||
|
} else {
|
||||||
|
blend_colors(egui::Color32::from_rgb(165, 42, 42), text_color, 0.8) // Brown-like
|
||||||
|
};
|
||||||
|
let function_color = if visuals.dark_mode {
|
||||||
|
blend_colors(egui::Color32::from_rgb(255, 20, 147), text_color, 0.8) // DeepPink-like
|
||||||
|
} else {
|
||||||
|
blend_colors(egui::Color32::from_rgb(128, 0, 128), text_color, 0.8) // Purple-like
|
||||||
|
};
|
||||||
|
|
||||||
|
let plist_theme = build_custom_theme_plist("System", &format!("{:?}", bg_color), &format!("{:?}", text_color), &format!("{:?}", comment_color), &format!("{:?}", string_color), &format!("{:?}", keyword_color));
|
||||||
|
let file = std::fs::File::create("system.tmTheme").unwrap();
|
||||||
|
let writer = std::io::BufWriter::new(file);
|
||||||
|
|
||||||
|
let _ =plist::to_writer_xml(writer, &plist_theme);
|
||||||
|
|
||||||
|
let loaded_file = std::fs::File::open("system.tmTheme").unwrap();
|
||||||
|
let mut loaded_reader = std::io::BufReader::new(loaded_file);
|
||||||
|
let loaded_theme = ThemeSet::load_from_reader(&mut loaded_reader).unwrap();
|
||||||
|
let mut set = ThemeSet::new();
|
||||||
|
set.add_from_folder(".").unwrap();
|
||||||
|
return set;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_custom_theme_plist(
|
||||||
|
theme_name: &str,
|
||||||
|
background_color: &str,
|
||||||
|
foreground_color: &str,
|
||||||
|
comment_color: &str,
|
||||||
|
string_color: &str,
|
||||||
|
keyword_color: &str,
|
||||||
|
) -> Value {
|
||||||
|
let mut root_dict = Dictionary::new();
|
||||||
|
root_dict.insert("name".to_string(), Value::String(theme_name.to_string()));
|
||||||
|
|
||||||
|
let mut settings_array = Vec::new();
|
||||||
|
|
||||||
|
// Global settings
|
||||||
|
let mut global_settings_dict = Dictionary::new();
|
||||||
|
let mut inner_global_settings = Dictionary::new();
|
||||||
|
inner_global_settings.insert("background".to_string(), Value::String(background_color.to_string()));
|
||||||
|
inner_global_settings.insert("foreground".to_string(), Value::String(foreground_color.to_string()));
|
||||||
|
global_settings_dict.insert("settings".to_string(), Value::Dictionary(inner_global_settings));
|
||||||
|
settings_array.push(Value::Dictionary(global_settings_dict));
|
||||||
|
|
||||||
|
// Comment scope
|
||||||
|
let mut comment_scope_dict = Dictionary::new();
|
||||||
|
comment_scope_dict.insert("name".to_string(), Value::String("Comment".to_string()));
|
||||||
|
comment_scope_dict.insert("scope".to_string(), Value::String("comment".to_string()));
|
||||||
|
let mut comment_settings = Dictionary::new();
|
||||||
|
comment_settings.insert("foreground".to_string(), Value::String(comment_color.to_string()));
|
||||||
|
comment_settings.insert("fontStyle".to_string(), Value::String("italic".to_string()));
|
||||||
|
comment_scope_dict.insert("settings".to_string(), Value::Dictionary(comment_settings));
|
||||||
|
settings_array.push(Value::Dictionary(comment_scope_dict));
|
||||||
|
|
||||||
|
// String scope
|
||||||
|
let mut string_scope_dict = Dictionary::new();
|
||||||
|
string_scope_dict.insert("name".to_string(), Value::String("String".to_string()));
|
||||||
|
string_scope_dict.insert("scope".to_string(), Value::String("string".to_string()));
|
||||||
|
let mut string_settings = Dictionary::new();
|
||||||
|
string_settings.insert("foreground".to_string(), Value::String(string_color.to_string()));
|
||||||
|
string_scope_dict.insert("settings".to_string(), Value::Dictionary(string_settings));
|
||||||
|
settings_array.push(Value::Dictionary(string_scope_dict));
|
||||||
|
|
||||||
|
// Keyword scope
|
||||||
|
let mut keyword_scope_dict = Dictionary::new();
|
||||||
|
keyword_scope_dict.insert("name".to_string(), Value::String("Keyword".to_string()));
|
||||||
|
keyword_scope_dict.insert("scope".to_string(), Value::String("keyword".to_string()));
|
||||||
|
let mut keyword_settings = Dictionary::new();
|
||||||
|
keyword_settings.insert("foreground".to_string(), Value::String(keyword_color.to_string()));
|
||||||
|
keyword_scope_dict.insert("settings".to_string(), Value::Dictionary(keyword_settings));
|
||||||
|
settings_array.push(Value::Dictionary(keyword_scope_dict));
|
||||||
|
|
||||||
|
// Add more scopes as needed...
|
||||||
|
|
||||||
|
root_dict.insert("settings".to_string(), Value::Array(settings_array));
|
||||||
|
|
||||||
|
Value::Dictionary(root_dict)
|
||||||
|
}
|
||||||
@ -4,7 +4,6 @@ use egui_extras::syntax_highlighting::{self};
|
|||||||
|
|
||||||
use super::find_highlight;
|
use super::find_highlight;
|
||||||
|
|
||||||
|
|
||||||
pub(super) fn editor_view_ui(ui: &mut egui::Ui, app: &mut TextEditor) -> egui::Response {
|
pub(super) fn editor_view_ui(ui: &mut egui::Ui, app: &mut TextEditor) -> egui::Response {
|
||||||
let _current_match_position = app.get_current_match_position();
|
let _current_match_position = app.get_current_match_position();
|
||||||
let show_find = app.show_find;
|
let show_find = app.show_find;
|
||||||
@ -101,11 +100,15 @@ pub(super) fn editor_view_ui(ui: &mut egui::Ui, app: &mut TextEditor) -> egui::R
|
|||||||
};
|
};
|
||||||
|
|
||||||
let language = super::languages::get_language_from_extension(active_tab.file_path.as_deref());
|
let language = super::languages::get_language_from_extension(active_tab.file_path.as_deref());
|
||||||
let theme = crate::app::theme::create_code_theme_from_visuals(ui.visuals(), font_size);
|
|
||||||
|
|
||||||
let mut layouter = |ui: &egui::Ui, string: &dyn egui::TextBuffer, wrap_width: f32| {
|
let mut layouter = |ui: &egui::Ui, string: &dyn egui::TextBuffer, wrap_width: f32| {
|
||||||
|
// let syntect_theme =
|
||||||
|
// crate::app::theme::create_code_theme_from_visuals(ui.visuals(), font_size);
|
||||||
let text = string.as_str();
|
let text = string.as_str();
|
||||||
|
let theme = egui_extras::syntax_highlighting::CodeTheme::dark(font_size);
|
||||||
let mut layout_job = if syntax_highlighting_enabled && language != "txt" {
|
let mut layout_job = if syntax_highlighting_enabled && language != "txt" {
|
||||||
|
// let mut settings = egui_extras::syntax_highlighting::SyntectSettings::default();
|
||||||
|
// settings.ts = syntect_theme;
|
||||||
|
// syntax_highlighting::highlight_with(ui.ctx(), &ui.style().clone(), &theme, text, &language, &settings)
|
||||||
syntax_highlighting::highlight(ui.ctx(), &ui.style().clone(), &theme, text, &language)
|
syntax_highlighting::highlight(ui.ctx(), &ui.style().clone(), &theme, text, &language)
|
||||||
} else {
|
} else {
|
||||||
syntax_highlighting::highlight(ui.ctx(), &ui.style().clone(), &theme, text, "")
|
syntax_highlighting::highlight(ui.ctx(), &ui.style().clone(), &theme, text, "")
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
pub fn get_language_from_extension(file_path: Option<&std::path::Path>) -> String {
|
pub fn get_language_from_extension(file_path: Option<&std::path::Path>) -> String {
|
||||||
if let Some(path) = file_path {
|
let default_lang = "txt".to_string();
|
||||||
|
|
||||||
|
let path = match file_path {
|
||||||
|
Some(p) => p,
|
||||||
|
None => return default_lang,
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(extension) = path.extension().and_then(|ext| ext.to_str()) {
|
if let Some(extension) = path.extension().and_then(|ext| ext.to_str()) {
|
||||||
match extension.to_lowercase().as_str() {
|
match extension.to_lowercase().as_str() {
|
||||||
"rs" => "rs".to_string(),
|
"rs" => "rs".to_string(),
|
||||||
@ -33,23 +39,17 @@ pub fn get_language_from_extension(file_path: Option<&std::path::Path>) -> Strin
|
|||||||
"vim" => "vim".to_string(),
|
"vim" => "vim".to_string(),
|
||||||
"dockerfile" => "dockerfile".to_string(),
|
"dockerfile" => "dockerfile".to_string(),
|
||||||
"makefile" => "makefile".to_string(),
|
"makefile" => "makefile".to_string(),
|
||||||
_ => "txt".to_string(),
|
_ => default_lang,
|
||||||
}
|
}
|
||||||
} else {
|
} else if let Some(filename) = path.file_name().and_then(|name| name.to_str()) {
|
||||||
// Check filename for special cases
|
|
||||||
if let Some(filename) = path.file_name().and_then(|name| name.to_str()) {
|
|
||||||
match filename.to_lowercase().as_str() {
|
match filename.to_lowercase().as_str() {
|
||||||
"dockerfile" => "dockerfile".to_string(),
|
"dockerfile" => "dockerfile".to_string(),
|
||||||
"makefile" => "makefile".to_string(),
|
"makefile" => "makefile".to_string(),
|
||||||
"cargo.toml" | "pyproject.toml" => "toml".to_string(),
|
"cargo.toml" | "pyproject.toml" => "toml".to_string(),
|
||||||
"package.json" => "json".to_string(),
|
"package.json" => "json".to_string(),
|
||||||
_ => "txt".to_string(),
|
_ => default_lang,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
"txt".to_string()
|
default_lang
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
"txt".to_string()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user