Initial commit: md-manuscript editor

Rust/egui desktop app: draggable markdown file list, editor, git sync,
per-file chapter titles, and native ODT export. Includes README and
Debian 12 (Surface) install guide.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
landon
2026-07-25 15:17:42 -05:00
commit f473b63ee3
11 changed files with 6201 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
/// Persistent application configuration (which workspace to open, plus UI prefs).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
/// Directory that holds the markdown files and the git repository.
pub workspace: PathBuf,
/// Last used ODT export path.
pub export_path: PathBuf,
/// Whether to show the live preview pane.
#[serde(default)]
pub show_preview: bool,
}
impl Default for Config {
fn default() -> Self {
let workspace = default_workspace();
let export_path = workspace.join("manuscript.odt");
Config {
workspace,
export_path,
show_preview: false,
}
}
}
/// The dedicated directory where manuscripts live by default: ~/Manuscript.
pub fn default_workspace() -> PathBuf {
dirs::home_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join("Manuscript")
}
/// Location of the config file: ~/.config/md-manuscript/config.json
fn config_path() -> PathBuf {
dirs::config_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join("md-manuscript")
.join("config.json")
}
impl Config {
pub fn load() -> Config {
let path = config_path();
match std::fs::read_to_string(&path) {
Ok(text) => serde_json::from_str(&text).unwrap_or_default(),
Err(_) => Config::default(),
}
}
pub fn save(&self) {
let path = config_path();
if let Some(parent) = path.parent() {
let _ = std::fs::create_dir_all(parent);
}
if let Ok(text) = serde_json::to_string_pretty(self) {
let _ = std::fs::write(&path, text);
}
}
}