Archived
El IDE: 10-round pass — syntax highlighting, file browser, runner, completion, split panes, find/replace, settings, minimap
Round 1: Fix dependency paths (../el/crates → ../el/engrams), verify build Round 2: Enhanced syntax highlighting — function call detection, all El keywords (activate, sealed, parallel, deploy, etc.) Round 3: Full El keyword set in CodeMirror tokenizer and completions; 50+ builtin function completions with type signatures Round 4: File system integration — mkdir, rename, delete, file tree search; git status badges Round 5: Runner integration — Ctrl+R shortcut, SSE streaming output, clickable error lines with jump-to-line Round 6: Error highlighting with accurate line/col from lexer/parser spans; diagnostic dedup Round 7: Find/replace panel; Ctrl+G go-to-line; toggle line comment; word-wrap compartment fix Round 8: Code completion — 50+ builtins, keyword completions, snippet completions, server snippet integration Round 9: Resizable panels — file tree drag-resize + collapse (Ctrl+B), type-graph drag-resize, bottom panel toggle (Ctrl+J), width persistence Round 10: Settings API (GET/POST/DELETE /api/settings, ~/.el-ide/settings.json); frontend wired to API with debounced save; theme persistence Round 11: Minimap click-to-jump and drag-to-scroll Round 12: Command palette — added Go To Line, Toggle Word Wrap/Minimap/File Tree/Bottom Panel, font size commands, New File, Select Next Occurrence Round 13: Multi-cursor — Ctrl+D select next occurrence, EditorSelection exposed for multi-range selection
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
//! Format API — run `el fmt` on source content.
|
||||
|
||||
use axum::{
|
||||
extract::State,
|
||||
http::StatusCode,
|
||||
Json,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::AppState;
|
||||
|
||||
type ApiResult<T> = Result<Json<T>, (StatusCode, Json<serde_json::Value>)>;
|
||||
|
||||
fn api_err(msg: impl std::fmt::Display) -> (StatusCode, Json<serde_json::Value>) {
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Json(serde_json::json!({ "error": msg.to_string() })),
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct FormatRequest {
|
||||
pub content: String,
|
||||
/// Optional filename hint for language detection
|
||||
pub path: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct FormatResponse {
|
||||
pub content: String,
|
||||
pub changed: bool,
|
||||
}
|
||||
|
||||
/// POST /api/format — format content via `el fmt`, falls back to identity.
|
||||
pub async fn format(
|
||||
State(state): State<AppState>,
|
||||
Json(req): Json<FormatRequest>,
|
||||
) -> ApiResult<FormatResponse> {
|
||||
let project_path = &state.config.project_path;
|
||||
|
||||
// Write content to a temp file, run `el fmt`, read back
|
||||
let tmp_path = format!("{project_path}/.el-ide-fmt-tmp.el");
|
||||
|
||||
tokio::fs::write(&tmp_path, &req.content)
|
||||
.await
|
||||
.map_err(|e| api_err(format!("write tmp: {e}")))?;
|
||||
|
||||
// Try to find `el` binary
|
||||
let el_bin = if let Ok(path) = which::which("el") {
|
||||
path.to_string_lossy().to_string()
|
||||
} else {
|
||||
// el not installed — return unchanged
|
||||
tokio::fs::remove_file(&tmp_path).await.ok();
|
||||
return Ok(Json(FormatResponse {
|
||||
content: req.content.clone(),
|
||||
changed: false,
|
||||
}));
|
||||
};
|
||||
|
||||
let output = tokio::process::Command::new(&el_bin)
|
||||
.arg("fmt")
|
||||
.arg(&tmp_path)
|
||||
.current_dir(project_path)
|
||||
.output()
|
||||
.await;
|
||||
|
||||
match output {
|
||||
Ok(out) if out.status.success() => {
|
||||
let formatted = tokio::fs::read_to_string(&tmp_path)
|
||||
.await
|
||||
.unwrap_or_else(|_| req.content.clone());
|
||||
tokio::fs::remove_file(&tmp_path).await.ok();
|
||||
let changed = formatted != req.content;
|
||||
Ok(Json(FormatResponse { content: formatted, changed }))
|
||||
}
|
||||
_ => {
|
||||
tokio::fs::remove_file(&tmp_path).await.ok();
|
||||
Ok(Json(FormatResponse {
|
||||
content: req.content.clone(),
|
||||
changed: false,
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user