1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 // rust - central access to other rust tools
12 // FIXME #2238 Make commands run and test emit proper file endings on windows
13 // FIXME #2238 Make run only accept source that emits an executable
17 uuid = "4a24da33-5cc8-4037-9352-2cbe9bd9d27c",
18 url = "https://github.com/mozilla/rust/tree/master/src/rust")];
20 #[license = "MIT/ASL2"];
21 #[crate_type = "lib"];
38 fn is_valid(&self) -> bool {
47 Call(extern "Rust" fn(args: &[~str]) -> ValidUsage),
48 CallMain(&'static str, extern "Rust" fn()),
51 enum UsageSource<'self> {
53 UsgCall(extern "Rust" fn()),
56 struct Command<'self> {
59 usage_line: &'self str,
60 usage_full: UsageSource<'self>,
63 static NUM_OF_COMMANDS: uint = 7;
65 // FIXME(#7617): should just be &'static [Command<'static>]
66 // but mac os doesn't seem to like that and tries to loop
67 // past the end of COMMANDS in usage thus passing garbage
68 // to str::repeat and eventually malloc and crashing.
69 static COMMANDS: [Command<'static>, .. NUM_OF_COMMANDS] = [
72 action: CallMain("rustc", rustc::main),
73 usage_line: "compile rust source files",
74 usage_full: UsgCall(rustc_help),
78 action: Call(cmd_run),
79 usage_line: "build an executable, and run it",
81 "The run command is an shortcut for the command line \n\
82 \"rustc <filename> -o <filestem>~ && ./<filestem>~ [<arguments>...]\".\
83 \n\nUsage:\trust run <filename> [<arguments>...]"
88 action: Call(cmd_test),
89 usage_line: "build a test executable, and run it",
91 "The test command is an shortcut for the command line \n\
92 \"rustc --test <filename> -o <filestem>test~ && \
93 ./<filestem>test~\"\n\nUsage:\trust test <filename>"
98 action: CallMain("rustdoc", rustdoc::main),
99 usage_line: "generate documentation from doc comments",
100 usage_full: UsgCall(rustdoc::config::usage),
104 action: CallMain("rustpkg", rustpkg::main),
105 usage_line: "download, build, install rust packages",
106 usage_full: UsgCall(rustpkg::usage::general),
110 action: CallMain("rusti", rusti::main),
111 usage_line: "run a rust interpreter",
112 usage_full: UsgStr("\nUsage:\trusti"),
116 action: Call(cmd_help),
117 usage_line: "show detailed usage of a command",
119 "The help command displays the usage text of another command.\n\
120 The text is either build in, or provided by the corresponding \
121 program.\n\nUsage:\trust help <command>"
127 rustc::usage(os::args()[0].clone())
130 fn find_cmd(command_string: &str) -> Option<Command> {
131 do COMMANDS.iter().find |command| {
132 command.cmd == command_string
136 fn cmd_help(args: &[~str]) -> ValidUsage {
137 fn print_usage(command_string: ~str) -> ValidUsage {
138 match find_cmd(command_string) {
140 match command.action {
141 CallMain(prog, _) => printfln!(
142 "The %s command is an alias for the %s program.",
146 match command.usage_full {
147 UsgStr(msg) => printfln!("%s\n", msg),
157 [ref command_string] => print_usage((*command_string).clone()),
162 fn cmd_test(args: &[~str]) -> ValidUsage {
165 let test_exec = Path(*filename).filestem().unwrap() + "test~";
166 invoke("rustc", &[~"--test", filename.to_owned(),
167 ~"-o", test_exec.to_owned()], rustc::main);
168 let exit_code = run::process_status(~"./" + test_exec, []);
175 fn cmd_run(args: &[~str]) -> ValidUsage {
177 [ref filename, ..prog_args] => {
178 let exec = Path(*filename).filestem().unwrap() + "~";
179 invoke("rustc", &[filename.to_owned(), ~"-o", exec.to_owned()],
181 let exit_code = run::process_status(~"./"+exec, prog_args);
188 fn invoke(prog: &str, args: &[~str], f: &fn()) {
189 let mut osargs = ~[prog.to_owned()];
190 osargs.push_all_move(args.to_owned());
191 os::set_args(osargs);
195 fn do_command(command: &Command, args: &[~str]) -> ValidUsage {
196 match command.action {
198 CallMain(prog, f) => {
199 invoke(prog, args, f);
206 static INDENT: uint = 8;
209 "The rust tool is a convenience for managing rust source code.\n\
210 It acts as a shortcut for programs of the rust tool chain.\n\
212 Usage:\trust <command> [arguments]\n\
218 for command in COMMANDS.iter() {
219 let padding = " ".repeat(INDENT - command.cmd.len());
220 printfln!(" %s%s%s", command.cmd, padding, command.usage_line);
225 Use \"rust help <command>\" for more information about a command.\n\
232 #[fixed_stack_segment]; #[inline(never)];
234 let os_args = os::args();
236 if (os_args.len() > 1 && (os_args[1] == ~"-v" || os_args[1] == ~"--version")) {
237 rustc::version(os_args[0]);
241 let args = os_args.tail();
243 if !args.is_empty() {
244 let r = find_cmd(*args.head());
245 for command in r.iter() {
246 let result = do_command(command, args.tail());
248 Valid(exit_code) => unsafe { exit(exit_code.to_i32()) },