add all project files

This commit is contained in:
Luna
2026-04-04 00:40:12 +02:00
parent 3909cfcf95
commit 97eb3eb021
82 changed files with 14174 additions and 0 deletions

7
src-tauri/.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
# Generated by Cargo
# will have compiled files and executables
/target/
# Generated by Tauri
# will have schema files for capabilities auto-completion
/gen/schemas

5159
src-tauri/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

21
src-tauri/Cargo.toml Normal file
View File

@@ -0,0 +1,21 @@
[package]
name = "lunar-code"
version = "0.1.0"
description = "Lunar Code - A lightweight code editor"
authors = ["luna"]
edition = "2021"
[lib]
name = "lunar_code_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
tauri-build = { version = "2", features = [] }
[dependencies]
tauri = { version = "2", features = [] }
tauri-plugin-fs = "2"
tauri-plugin-dialog = "2"
tauri-plugin-shell = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"

3
src-tauri/build.rs Normal file
View File

@@ -0,0 +1,3 @@
fn main() {
tauri_build::build()
}

View File

@@ -0,0 +1,43 @@
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Capability for the main window",
"windows": ["main"],
"permissions": [
"core:default",
"dialog:default",
"dialog:allow-open",
"dialog:allow-save",
"dialog:allow-ask",
"dialog:allow-confirm",
"dialog:allow-message",
"fs:default",
"fs:read-all",
"fs:write-all",
"fs:scope-home-recursive",
"shell:default",
"shell:allow-open",
{
"identifier": "shell:allow-execute",
"allow": [
{
"name": "exec-sh",
"cmd": "sh",
"args": true
}
]
},
{
"identifier": "shell:allow-spawn",
"allow": [
{
"name": "exec-sh",
"cmd": "sh",
"args": true
}
]
},
"shell:allow-stdin-write",
"shell:allow-kill"
]
}

BIN
src-tauri/icons/128x128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
src-tauri/icons/32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src-tauri/icons/icon.icns Normal file

Binary file not shown.

BIN
src-tauri/icons/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
src-tauri/icons/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

232
src-tauri/src/lib.rs Normal file
View File

@@ -0,0 +1,232 @@
use std::fs;
use std::io::BufRead;
use std::path::Path;
#[derive(serde::Serialize)]
pub struct DirEntry {
pub name: String,
pub path: String,
pub is_dir: bool,
}
#[tauri::command]
fn read_directory(path: String) -> Result<Vec<DirEntry>, String> {
let dir_path = Path::new(&path);
if !dir_path.is_dir() {
return Err(format!("{} is not a directory", path));
}
let mut entries: Vec<DirEntry> = Vec::new();
let read_dir = fs::read_dir(dir_path).map_err(|e| e.to_string())?;
for entry in read_dir {
let entry = entry.map_err(|e| e.to_string())?;
let file_name = entry.file_name().to_string_lossy().to_string();
if file_name.starts_with('.') {
continue;
}
let file_path = entry.path().to_string_lossy().to_string();
let is_dir = entry.path().is_dir();
entries.push(DirEntry {
name: file_name,
path: file_path,
is_dir,
});
}
entries.sort_by(|a, b| {
if a.is_dir == b.is_dir {
a.name.to_lowercase().cmp(&b.name.to_lowercase())
} else if a.is_dir {
std::cmp::Ordering::Less
} else {
std::cmp::Ordering::Greater
}
});
Ok(entries)
}
#[tauri::command]
fn read_file(path: String) -> Result<String, String> {
fs::read_to_string(&path).map_err(|e| format!("Failed to read {}: {}", path, e))
}
#[tauri::command]
fn write_file(path: String, contents: String) -> Result<(), String> {
fs::write(&path, contents).map_err(|e| format!("Failed to write {}: {}", path, e))
}
#[tauri::command]
fn create_file(path: String) -> Result<(), String> {
if Path::new(&path).exists() {
return Err(format!("{} already exists", path));
}
fs::write(&path, "").map_err(|e| e.to_string())
}
#[tauri::command]
fn create_directory(path: String) -> Result<(), String> {
fs::create_dir_all(&path).map_err(|e| e.to_string())
}
#[tauri::command]
fn rename_path(old_path: String, new_path: String) -> Result<(), String> {
fs::rename(&old_path, &new_path).map_err(|e| e.to_string())
}
#[tauri::command]
fn delete_path(path: String) -> Result<(), String> {
let p = Path::new(&path);
if p.is_dir() {
fs::remove_dir_all(p).map_err(|e| e.to_string())
} else {
fs::remove_file(p).map_err(|e| e.to_string())
}
}
#[derive(serde::Serialize)]
pub struct SearchMatch {
pub file_path: String,
pub file_name: String,
pub line_number: usize,
pub line_content: String,
pub match_start: usize,
pub match_end: usize,
}
const SKIP_DIRS: &[&str] = &[
"node_modules", "target", ".git", "dist", "build", "__pycache__",
".next", ".nuxt", "vendor", ".venv", "venv",
];
fn search_dir(
dir: &Path,
query: &str,
case_sensitive: bool,
results: &mut Vec<SearchMatch>,
max_results: usize,
) {
if results.len() >= max_results {
return;
}
let read_dir = match fs::read_dir(dir) {
Ok(rd) => rd,
Err(_) => return,
};
let mut entries: Vec<_> = read_dir.filter_map(|e| e.ok()).collect();
entries.sort_by(|a, b| a.file_name().cmp(&b.file_name()));
for entry in entries {
if results.len() >= max_results {
return;
}
let name = entry.file_name().to_string_lossy().to_string();
if name.starts_with('.') {
continue;
}
let path = entry.path();
if path.is_dir() {
if SKIP_DIRS.contains(&name.as_str()) {
continue;
}
search_dir(&path, query, case_sensitive, results, max_results);
} else {
search_file(&path, &name, query, case_sensitive, results, max_results);
}
}
}
fn search_file(
path: &Path,
name: &str,
query: &str,
case_sensitive: bool,
results: &mut Vec<SearchMatch>,
max_results: usize,
) {
let file = match fs::File::open(path) {
Ok(f) => f,
Err(_) => return,
};
// Skip binary/large files
let metadata = match file.metadata() {
Ok(m) => m,
Err(_) => return,
};
if metadata.len() > 2_000_000 {
return;
}
let reader = std::io::BufReader::new(file);
let query_lower = if case_sensitive { query.to_string() } else { query.to_lowercase() };
let path_str = path.to_string_lossy().to_string();
for (i, line) in reader.lines().enumerate() {
if results.len() >= max_results {
return;
}
let line = match line {
Ok(l) => l,
Err(_) => return, // likely binary
};
let search_line = if case_sensitive { line.clone() } else { line.to_lowercase() };
if let Some(pos) = search_line.find(&query_lower) {
results.push(SearchMatch {
file_path: path_str.clone(),
file_name: name.to_string(),
line_number: i + 1,
line_content: line.chars().take(500).collect(),
match_start: pos,
match_end: pos + query.len(),
});
}
}
}
#[tauri::command]
fn search_in_files(
dir: String,
query: String,
case_sensitive: bool,
) -> Result<Vec<SearchMatch>, String> {
let dir_path = Path::new(&dir);
if !dir_path.is_dir() {
return Err(format!("{} is not a directory", dir));
}
if query.is_empty() {
return Ok(vec![]);
}
let mut results = Vec::new();
search_dir(dir_path, &query, case_sensitive, &mut results, 1000);
Ok(results)
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_shell::init())
.invoke_handler(tauri::generate_handler![
read_directory,
read_file,
write_file,
create_file,
create_directory,
rename_path,
delete_path,
search_in_files,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

6
src-tauri/src/main.rs Normal file
View File

@@ -0,0 +1,6 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
lunar_code_lib::run()
}

45
src-tauri/tauri.conf.json Normal file
View File

@@ -0,0 +1,45 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Lunar Code",
"version": "0.1.0",
"identifier": "com.luna.lunar-code",
"build": {
"beforeDevCommand": "pnpm dev",
"devUrl": "http://localhost:1420",
"beforeBuildCommand": "pnpm build",
"frontendDist": "../dist"
},
"app": {
"windows": [
{
"title": "Lunar Code",
"width": 1200,
"height": 800,
"minWidth": 640,
"minHeight": 480
}
],
"security": {
"csp": null
}
},
"bundle": {
"active": true,
"targets": "all",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
]
},
"plugins": {
"fs": {
"requireLiteralLeadingDot": false
},
"shell": {
"open": true
}
}
}