feat: implement package manager
Adds dependency management for Lux projects: - `lux pkg install` - Install all dependencies from lux.toml - `lux pkg add <pkg>` - Add a dependency (supports --git, --path) - `lux pkg remove <pkg>` - Remove a dependency - `lux pkg list` - List dependencies with install status - `lux pkg update` - Update all dependencies - `lux pkg clean` - Remove installed packages Supports three dependency sources: - Registry (placeholder for future package registry) - Git repositories (with optional branch) - Local file paths Packages are installed to .lux_packages/ in the project root. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
156
src/main.rs
156
src/main.rs
@@ -9,6 +9,7 @@ mod interpreter;
|
||||
mod lexer;
|
||||
mod lsp;
|
||||
mod modules;
|
||||
mod package;
|
||||
mod parser;
|
||||
mod schema;
|
||||
mod typechecker;
|
||||
@@ -133,6 +134,10 @@ fn main() {
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
"pkg" => {
|
||||
// Package manager
|
||||
handle_pkg_command(&args[2..]);
|
||||
}
|
||||
path => {
|
||||
// Run a file
|
||||
run_file(path);
|
||||
@@ -156,6 +161,7 @@ fn print_help() {
|
||||
println!(" lux watch <file.lux> Watch and re-run on changes");
|
||||
println!(" lux debug <file.lux> Start interactive debugger");
|
||||
println!(" lux init [name] Initialize a new project");
|
||||
println!(" lux pkg <command> Package manager (install, add, remove, list, update)");
|
||||
println!(" lux --lsp Start LSP server (for IDE integration)");
|
||||
println!(" lux --help Show this help");
|
||||
println!(" lux --version Show version");
|
||||
@@ -382,6 +388,156 @@ fn watch_file(path: &str) {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_pkg_command(args: &[String]) {
|
||||
use package::{PackageManager, DependencySource};
|
||||
use std::path::PathBuf;
|
||||
|
||||
if args.is_empty() {
|
||||
print_pkg_help();
|
||||
return;
|
||||
}
|
||||
|
||||
// Help doesn't require being in a project
|
||||
if matches!(args[0].as_str(), "help" | "--help" | "-h") {
|
||||
print_pkg_help();
|
||||
return;
|
||||
}
|
||||
|
||||
let project_root = match PackageManager::find_project_root() {
|
||||
Some(root) => root,
|
||||
None => {
|
||||
eprintln!("Error: Not in a Lux project (no lux.toml found)");
|
||||
eprintln!("Run 'lux init' to create a new project");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let pkg = PackageManager::new(&project_root);
|
||||
|
||||
match args[0].as_str() {
|
||||
"install" | "i" => {
|
||||
if let Err(e) = pkg.install() {
|
||||
eprintln!("Error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
"add" => {
|
||||
if args.len() < 2 {
|
||||
eprintln!("Usage: lux pkg add <package> [version] [--git <url>] [--path <path>]");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let name = &args[1];
|
||||
let mut version = "0.0.0".to_string();
|
||||
let mut source = DependencySource::Registry;
|
||||
|
||||
let mut i = 2;
|
||||
while i < args.len() {
|
||||
match args[i].as_str() {
|
||||
"--git" => {
|
||||
if i + 1 < args.len() {
|
||||
let url = args[i + 1].clone();
|
||||
let branch = if i + 3 < args.len() && args[i + 2] == "--branch" {
|
||||
i += 2;
|
||||
Some(args[i + 1].clone())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
source = DependencySource::Git { url, branch };
|
||||
i += 2;
|
||||
} else {
|
||||
eprintln!("--git requires a URL");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
"--path" => {
|
||||
if i + 1 < args.len() {
|
||||
source = DependencySource::Path {
|
||||
path: PathBuf::from(&args[i + 1]),
|
||||
};
|
||||
i += 2;
|
||||
} else {
|
||||
eprintln!("--path requires a path");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
v if !v.starts_with('-') => {
|
||||
version = v.to_string();
|
||||
i += 1;
|
||||
}
|
||||
_ => i += 1,
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(e) = pkg.add(name, &version, source) {
|
||||
eprintln!("Error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
"remove" | "rm" => {
|
||||
if args.len() < 2 {
|
||||
eprintln!("Usage: lux pkg remove <package>");
|
||||
std::process::exit(1);
|
||||
}
|
||||
if let Err(e) = pkg.remove(&args[1]) {
|
||||
eprintln!("Error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
"list" | "ls" => {
|
||||
if let Err(e) = pkg.list() {
|
||||
eprintln!("Error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
"update" => {
|
||||
if let Err(e) = pkg.update() {
|
||||
eprintln!("Error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
"clean" => {
|
||||
if let Err(e) = pkg.clean() {
|
||||
eprintln!("Error: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
"help" | "--help" | "-h" => {
|
||||
print_pkg_help();
|
||||
}
|
||||
unknown => {
|
||||
eprintln!("Unknown package command: {}", unknown);
|
||||
print_pkg_help();
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_pkg_help() {
|
||||
println!("Lux Package Manager");
|
||||
println!();
|
||||
println!("Usage: lux pkg <command> [options]");
|
||||
println!();
|
||||
println!("Commands:");
|
||||
println!(" install, i Install all dependencies from lux.toml");
|
||||
println!(" add <pkg> Add a dependency");
|
||||
println!(" Options:");
|
||||
println!(" [version] Specify version (default: 0.0.0)");
|
||||
println!(" --git <url> Install from git repository");
|
||||
println!(" --branch <name> Git branch (with --git)");
|
||||
println!(" --path <path> Install from local path");
|
||||
println!(" remove, rm Remove a dependency");
|
||||
println!(" list, ls List dependencies and their status");
|
||||
println!(" update Update all dependencies");
|
||||
println!(" clean Remove installed packages");
|
||||
println!();
|
||||
println!("Examples:");
|
||||
println!(" lux pkg install");
|
||||
println!(" lux pkg add http 1.0.0");
|
||||
println!(" lux pkg add mylib --git https://github.com/user/mylib");
|
||||
println!(" lux pkg add local-lib --path ../lib");
|
||||
println!(" lux pkg remove http");
|
||||
}
|
||||
|
||||
fn init_project(name: Option<&str>) {
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
Reference in New Issue
Block a user