193 lines
6.0 KiB
Rust
Executable File
193 lines
6.0 KiB
Rust
Executable File
use iced::widget::text_editor;
|
|
use std::fs;
|
|
use std::path::PathBuf;
|
|
|
|
pub struct EditorTab {
|
|
pub title: String,
|
|
pub content: text_editor::Content,
|
|
pub is_dirty: bool,
|
|
pub file_path: Option<PathBuf>,
|
|
pub override_syntax: Option<String>,
|
|
pub symbols: Vec<(usize, String)>,
|
|
pub bookmarks: Vec<usize>,
|
|
}
|
|
|
|
impl EditorTab {
|
|
pub fn new(title: &str, initial_text: &str) -> Self {
|
|
let mut tab = Self {
|
|
title: title.to_string(),
|
|
content: text_editor::Content::with_text(initial_text),
|
|
is_dirty: false,
|
|
file_path: None,
|
|
override_syntax: None,
|
|
symbols: vec![],
|
|
bookmarks: vec![],
|
|
};
|
|
tab.parse_symbols();
|
|
tab
|
|
}
|
|
|
|
pub fn parse_symbols(&mut self) {
|
|
self.symbols.clear();
|
|
for (i, line) in self.content.text().lines().enumerate() {
|
|
let t = line.trim_start();
|
|
if t.starts_with("fn ")
|
|
|| t.starts_with("def ")
|
|
|| t.starts_with("class ")
|
|
|| t.starts_with("struct ")
|
|
|| t.starts_with("impl ")
|
|
|| t.starts_with("enum ")
|
|
|| t.starts_with("trait ")
|
|
|| t.starts_with("mod ")
|
|
|| t.starts_with("pub fn ")
|
|
|| t.starts_with("pub struct ")
|
|
|| t.starts_with("pub enum ")
|
|
|| t.starts_with("pub trait ")
|
|
|| t.starts_with("pub mod ")
|
|
|| t.starts_with("macro_rules!")
|
|
{
|
|
let name = t
|
|
.split('{')
|
|
.next()
|
|
.unwrap_or(t)
|
|
.split('(')
|
|
.next()
|
|
.unwrap_or(t)
|
|
.split('!')
|
|
.next()
|
|
.unwrap_or(t)
|
|
.trim()
|
|
.to_string();
|
|
self.symbols.push((i + 1, name));
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn toggle_bookmark(&mut self, line: usize) {
|
|
if self.bookmarks.contains(&line) {
|
|
self.bookmarks.retain(|&b| b != line);
|
|
} else {
|
|
self.bookmarks.push(line);
|
|
self.bookmarks.sort();
|
|
}
|
|
}
|
|
|
|
pub fn save(&mut self) -> Result<String, std::io::Error> {
|
|
let path = self
|
|
.file_path
|
|
.clone()
|
|
.unwrap_or_else(|| PathBuf::from(&self.title));
|
|
let text = self.content.text();
|
|
fs::write(&path, text)?;
|
|
self.is_dirty = false;
|
|
self.file_path = Some(path.clone());
|
|
Ok(path.to_string_lossy().to_string())
|
|
}
|
|
|
|
pub fn save_as(&mut self, new_path: &str) -> Result<String, std::io::Error> {
|
|
let path = PathBuf::from(new_path);
|
|
let text = self.content.text();
|
|
fs::write(&path, text)?;
|
|
self.is_dirty = false;
|
|
self.file_path = Some(path.clone());
|
|
self.title = path
|
|
.file_name()
|
|
.unwrap_or_default()
|
|
.to_string_lossy()
|
|
.to_string();
|
|
Ok(path.to_string_lossy().to_string())
|
|
}
|
|
|
|
pub fn line_count(&self) -> usize {
|
|
self.content.text().lines().count().max(1)
|
|
}
|
|
|
|
pub fn byte_size(&self) -> usize {
|
|
self.content.text().len()
|
|
}
|
|
|
|
pub fn get_syntax(&self) -> &'static str {
|
|
if let Some(ref syn) = self.override_syntax {
|
|
return match syn.as_str() {
|
|
"Rust" => "rs",
|
|
"Python" => "py",
|
|
"C/C++" | "C" | "C++" => "cpp",
|
|
"Shell" | "Bash" => "sh",
|
|
"JavaScript" => "js",
|
|
"TypeScript" => "ts",
|
|
"Markdown" => "md",
|
|
"HTML" => "html",
|
|
"CSS" => "css",
|
|
"JSON" => "json",
|
|
"XML" => "xml",
|
|
"YAML" => "yaml",
|
|
"Go" => "go",
|
|
"Ruby" => "rb",
|
|
"PHP" => "php",
|
|
"Java" => "java",
|
|
"C#" => "cs",
|
|
"SQL" => "sql",
|
|
_ => "txt",
|
|
};
|
|
}
|
|
|
|
let name = self.title.to_lowercase();
|
|
if name.contains("dockerfile") || name.contains("containerfile") {
|
|
return "dockerfile";
|
|
}
|
|
if name.contains("nginx") {
|
|
return "nginx";
|
|
}
|
|
if name.contains("apache") || name.contains("httpd") {
|
|
return "apache";
|
|
}
|
|
if name.ends_with("rc") {
|
|
return "sh";
|
|
}
|
|
if name.ends_with("makefile") || name == "makefile" {
|
|
return "makefile";
|
|
}
|
|
|
|
let parts: Vec<&str> = name.split('.').collect();
|
|
if let Some(ext) = parts.last() {
|
|
match *ext {
|
|
"rs" => "rs",
|
|
"sh" | "bash" | "zsh" | "command" => "sh",
|
|
"ps1" | "psm1" => "ps1",
|
|
"bat" | "cmd" | "dosbat" => "bat",
|
|
"vbs" | "vbe" | "wscript" | "vbasic" => "vbs",
|
|
"conf" | "cfg" | "ini" | "service" | "target" => "ini",
|
|
"yaml" | "yml" => "yaml",
|
|
"toml" => "toml",
|
|
"json" => "json",
|
|
"xml" => "xml",
|
|
"html" | "htm" | "xhtml" => "html",
|
|
"css" | "scss" | "sass" | "less" => "css",
|
|
"js" | "mjs" | "cjs" => "js",
|
|
"ts" | "tsx" => "ts",
|
|
"py" | "pyw" => "py",
|
|
"c" | "h" => "c",
|
|
"cpp" | "hpp" | "cc" | "cxx" | "hxx" => "cpp",
|
|
"go" => "go",
|
|
"rb" => "rb",
|
|
"php" | "phtml" => "php",
|
|
"java" => "java",
|
|
"cs" => "cs",
|
|
"sql" => "sql",
|
|
"md" | "markdown" => "md",
|
|
"r" => "r",
|
|
"lua" => "lua",
|
|
"pl" | "pm" => "pl",
|
|
"ex" | "exs" => "ex",
|
|
"hs" => "hs",
|
|
"scala" => "scala",
|
|
"swift" => "swift",
|
|
"kt" | "kts" => "kt",
|
|
"dart" => "dart",
|
|
_ => "txt",
|
|
}
|
|
} else {
|
|
"txt"
|
|
}
|
|
}
|
|
} |