mod builtins;
mod colors;
mod executor;
mod functions;
mod history;
mod parser;
mod path_utils;
mod ui;
mod variables;
use history::HistoryManager;
use repl::{LineEditor, ReadlineEvent, RealExecutor};
use rustyline::error::ReadlineError;
use rustyline::{history::DefaultHistory, Editor};
mod autocomplete;
mod completion_registry;
mod repl;
use autocomplete::PmshHelper;
use functions::Functions;
fn main() {
let history_mgr = HistoryManager::new().unwrap_or_else(|e| {
eprintln!("Warning: Could not initialize history: {}", e);
HistoryManager::default()
});
let mut command_history = history_mgr.load().unwrap_or_default();
let args: Vec<String> = std::env::args().collect();
if args.len() > 1 {
let script_path = &args[1];
let contents = std::fs::read_to_string(script_path).unwrap_or_else(|e| {
eprintln!("Error reading script {}: {}", script_path, e);
std::process::exit(1);
});
struct ScriptEditor;
impl LineEditor for ScriptEditor {
fn readline(&mut self, _prompt: &str) -> ReadlineEvent {
ReadlineEvent::Eof
}
fn add_history_entry(&mut self, _entry: &str) {}
}
let _editor = ScriptEditor;
let mut oldpwd: Option<String> = None;
let executor = RealExecutor {};
let mut vars = variables::Variables::new();
let mut functions = Functions::new();
use crate::parser::Command;
match Command::parse_script(&contents) {
Ok(pipelines) => {
for pipeline in pipelines {
if !repl::execute_pipeline_struct(
&pipeline,
&history_mgr,
&mut command_history,
&executor,
&mut oldpwd,
&mut vars,
&mut functions,
) {
break;
}
}
}
Err(e) => {
eprintln!("Error parsing script: {}", e);
std::process::exit(1);
}
}
} else {
let mut oldpwd: Option<String> = None;
let executor = RealExecutor {};
let mut vars = variables::Variables::new();
let mut functions = Functions::new();
if let Ok(home) = std::env::var("HOME") {
let mut home_dir = std::path::PathBuf::from(home);
home_dir.push(".pmshrc");
if home_dir.exists() {
if let Ok(contents) = std::fs::read_to_string(&home_dir) {
use crate::parser::Command;
if let Ok(pipelines) = Command::parse_script(&contents) {
for pipeline in pipelines {
repl::execute_pipeline_struct(
&pipeline,
&history_mgr,
&mut command_history,
&executor,
&mut oldpwd,
&mut vars,
&mut functions,
);
}
} else {
eprintln!("pmsh: error parsing ~/.pmshrc");
}
}
}
}
let config = rustyline::Config::builder()
.completion_type(rustyline::CompletionType::List)
.build();
let mut rl: Editor<PmshHelper, DefaultHistory> =
Editor::with_config(config).expect("Failed to create editor");
rl.set_helper(Some(PmshHelper::new()));
for entry in &command_history {
let _ = rl.add_history_entry(entry.as_str());
}
struct RustyEditor {
inner: Editor<PmshHelper, DefaultHistory>,
}
impl LineEditor for RustyEditor {
fn readline(&mut self, prompt: &str) -> ReadlineEvent {
match self.inner.readline(prompt) {
Ok(line) => ReadlineEvent::Line(line),
Err(ReadlineError::Interrupted) => ReadlineEvent::Interrupted,
Err(ReadlineError::Eof) => ReadlineEvent::Eof,
Err(_e) => ReadlineEvent::Other,
}
}
fn add_history_entry(&mut self, entry: &str) {
let _ = self.inner.add_history_entry(entry);
}
}
let mut editor = RustyEditor { inner: rl };
repl::run_repl_with_state(
&mut editor,
&history_mgr,
&mut command_history,
&executor,
oldpwd,
vars,
functions,
);
}
}