use clap::{Parser, Subcommand};
use colored::*;
use std::fs;
use std::path::PathBuf;
use std::io::{self, Write};
use anyhow::Result;
use openscript_sdk::plugin::PluginManager;
use openscript_sdk::ai_plugin::AiPlugin;
use openscript_sdk::filesystem_plugin::FilesystemPlugin;
use openscript_sdk::http_plugin::HttpPlugin;
use openscript_sdk::system_plugin::SystemPlugin;
use openscript_sdk::utils_plugin::UtilsPlugin;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
#[command(name = "openscript")]
#[command(about = "OpenScript - AI-Powered Scripting Language")]
struct Cli {
#[command(subcommand)]
command: Option<Commands>,
}
#[derive(Subcommand)]
enum Commands {
Run {
file: PathBuf,
#[arg(short, long)]
verbose: bool,
#[arg(trailing_var_arg = true)]
args: Vec<String>,
},
Repl {
#[arg(long)]
ai: bool,
#[arg(short, long)]
load: Option<PathBuf>,
},
Eval {
script: String,
#[arg(short, long)]
verbose: bool,
},
Examples,
Check {
file: PathBuf,
},
Format {
file: PathBuf,
#[arg(short, long)]
write: bool,
},
Version,
}
#[tokio::main]
async fn main() -> Result<()> {
let cli = Cli::parse();
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
let mut plugin_manager = PluginManager::new();
plugin_manager.load_plugin(Box::new(AiPlugin::new())).await.map_err(|e| anyhow::anyhow!(e))?;
plugin_manager.load_plugin(Box::new(FilesystemPlugin::new())).await.map_err(|e| anyhow::anyhow!(e))?;
plugin_manager.load_plugin(Box::new(HttpPlugin::new())).await.map_err(|e| anyhow::anyhow!(e))?;
plugin_manager.load_plugin(Box::new(SystemPlugin::new())).await.map_err(|e| anyhow::anyhow!(e))?;
plugin_manager.load_plugin(Box::new(UtilsPlugin::new())).await.map_err(|e| anyhow::anyhow!(e))?;
match cli.command.unwrap_or(Commands::Repl { ai: false, load: None }) {
Commands::Run { file, verbose, args } => {
run_file(file, verbose, args, &plugin_manager).await?;
}
Commands::Repl { ai, load } => {
run_repl(ai, load, &plugin_manager).await?;
}
Commands::Eval { script, verbose } => {
run_script(&script, verbose, &plugin_manager).await?;
}
Commands::Examples => {
show_examples();
}
Commands::Check { file } => {
check_syntax(file).await?;
}
Commands::Format { file, write } => {
format_file(file, write).await?;
}
Commands::Version => {
show_version();
}
}
Ok(())
}
async fn run_file(path: PathBuf, verbose: bool, _args: Vec<String>, plugin_manager: &PluginManager) -> Result<()> {
if verbose {
println!("{}", " OpenScript v1.0.0".bright_blue().bold());
println!("{}", format!(" Running: {}", path.display()).yellow());
}
let script = fs::read_to_string(&path)?;
run_script(&script, verbose, plugin_manager).await
}
async fn run_script(script: &str, verbose: bool, plugin_manager: &PluginManager) -> Result<()> {
if verbose {
println!("{}", " OpenScript v1.0.0".bright_blue().bold());
}
for line in script.lines() {
let parts: Vec<String> = line.split_whitespace().map(|s| s.to_string()).collect();
if parts.is_empty() {
continue;
}
let command_name = &parts[0];
let args = &parts[1..];
if let Some(command) = plugin_manager.get_command(command_name) {
match command.execute(args).await {
Ok(result) => {
if !result.is_empty() {
println!("{}", result);
}
}
Err(e) => {
eprintln!("{}", format!("Error: {}", e).red());
}
}
} else {
eprintln!("{}", format!("Unknown command: {}", command_name).red());
}
}
Ok(())
}
async fn run_repl(ai_enabled: bool, load_file: Option<PathBuf>, plugin_manager: &PluginManager) -> Result<()> {
println!("{}", " OpenScript REPL v1.0.0".bright_blue().bold());
if ai_enabled {
if std::env::var("OPENAI_API_KEY").is_ok() {
println!("{}", " AI assistance enabled".green());
} else {
println!("{}", "Warning: AI assistance requested but OPENAI_API_KEY not set".yellow());
}
}
println!("{}", "Type 'help' for commands, 'exit' to quit\n".dimmed());
if let Some(file_path) = load_file {
let script = fs::read_to_string(&file_path)?;
println!("{}", format!(" Loaded {}", file_path.display()).green());
println!("Script content:");
println!("{}", script.dimmed());
println!();
}
let mut line_number = 1;
loop {
let prompt = format!("{} ", format!("[{}]►", line_number).green());
print!("{}", prompt);
io::stdout().flush()?;
let mut input = String::new();
io::stdin().read_line(&mut input)?;
let input = input.trim();
match input {
"exit" | "quit" => break,
"help" => {
print_help();
continue;
}
"clear" => {
print!("\x1B[2J\x1B[1;1H");
continue;
}
_ => {}
}
let parts: Vec<String> = input.split_whitespace().map(|s| s.to_string()).collect();
if parts.is_empty() {
line_number += 1;
continue;
}
let command_name = &parts[0];
let args = &parts[1..];
if let Some(command) = plugin_manager.get_command(command_name) {
match command.execute(args).await {
Ok(result) => {
if !result.is_empty() {
println!("{}", result);
}
}
Err(e) => {
eprintln!("{}", format!("Error: {}", e).red());
}
}
} else {
eprintln!("{}", format!("Unknown command: {}", command_name).red());
}
line_number += 1;
}
println!("{}", "\nGoodbye!".bright_blue());
Ok(())
}
fn print_help() {
println!("{}", "\n OpenScript REPL Commands".bright_blue().bold());
println!("{}", "─".repeat(40).dimmed());
println!("{} {}", "help".bright_green(), "Show this help message");
println!("{} {}", "exit".bright_green(), "Exit the REPL");
println!("{} {}", "clear".bright_green(), "Clear the screen");
println!("{}", "─".repeat(40).dimmed());
println!("{}", "\n OpenScript Language Features".bright_blue().bold());
println!("{}", "─".repeat(40).dimmed());
println!("• Variables: {} = {}", "name".bright_yellow(), "\"value\"".bright_cyan());
println!("• Functions: {} {} {{ ... }}", "fn".bright_magenta(), "myFunc()".bright_yellow());
println!("• Control flow: {}, {}, {}", "if".bright_magenta(), "for".bright_magenta(), "while".bright_magenta());
println!("• AI features: {}, {}", "ai_complete()".bright_yellow(), "ai_image()".bright_yellow());
println!("{}", "─".repeat(40).dimmed());
println!();
}
fn show_examples() {
println!("{}", "\n OpenScript Examples".bright_blue().bold());
println!("{}", "─".repeat(60).dimmed());
println!("{}", "\n Basic Variables and Printing".bright_green().bold());
println!("{}", r#"name = "OpenScript"
print("Hello from " + name + "!")
"#.dimmed());
println!("{}", "\n Functions".bright_green().bold());
println!("{}", r#"fn greet(name) {
return "Hello, " + name + "!"
}
print(greet("World"))
"#.dimmed());
println!("{}", "\n Loops and Control Flow".bright_green().bold());
println!("{}", r#"for i in range(1, 5) {
if i % 2 == 0 {
print(i + " is even")
}
}
"#.dimmed());
println!("{}", "\n AI Integration".bright_green().bold());
println!("{}", r#"// Text completion
response = ai_complete("Write a haiku about programming")
print(response)
// Image generation
image_url = ai_image("futuristic city at sunset")
print("Generated image: " + image_url)
"#.dimmed());
println!("{}", "\n File Operations".bright_green().bold());
println!("{}", r#"// Write to file
write_file("output.txt", "Hello, OpenScript!")
// Read from file
content = read_file("output.txt")
print(content)
"#.dimmed());
println!("{}", "─".repeat(60).dimmed());
println!();
}
async fn check_syntax(path: PathBuf) -> Result<()> {
println!("{}", " Checking syntax...".yellow());
let script = fs::read_to_string(&path)?;
println!("{}", "Syntax checking not yet implemented".yellow());
println!("Script loaded successfully:");
println!("{} bytes", script.len());
Ok(())
}
async fn format_file(path: PathBuf, write: bool) -> Result<()> {
let script = fs::read_to_string(&path)?;
println!("{}", "Code formatting not yet implemented".yellow());
if write {
println!("{}", format!("Would format {}", path.display()).dimmed());
} else {
println!("Script content:");
println!("{}", script.dimmed());
}
Ok(())
}
fn show_version() {
println!("{}", " OpenScript".bright_blue().bold());
println!("{}", "─".repeat(40).dimmed());
println!("{} {}", "Version:".bright_green(), env!("CARGO_PKG_VERSION"));
println!("{} {}", "License:".bright_green(), "MIT OR Apache-2.0");
println!("{} {}", "Authors:".bright_green(), env!("CARGO_PKG_AUTHORS"));
println!("{}", "─".repeat(40).dimmed());
println!();
println!("{}", "Build Information".bright_blue().bold());
println!("{}", "─".repeat(40).dimmed());
println!("{} {}", "Target:".bright_green(), std::env::var("TARGET").unwrap_or_else(|_| "unknown".to_string()));
println!("{} {}", "Host:".bright_green(), std::env::var("HOST").unwrap_or_else(|_| "unknown".to_string()));
println!("{} {}", "Profile:".bright_green(), if cfg!(debug_assertions) { "debug" } else { "release" });
println!("{} {}", "Rustc:".bright_green(), std::env::var("RUSTC_VERSION").unwrap_or_else(|_| "unknown".to_string()));
println!("{}", "─".repeat(40).dimmed());
}