X-Git-Url: http://nitlanguage.org diff --git a/src/toolcontext.nit b/src/toolcontext.nit index b91fdad..5b9d020 100644 --- a/src/toolcontext.nit +++ b/src/toolcontext.nit @@ -21,6 +21,7 @@ module toolcontext import opts import location +import version class Message super Comparable @@ -89,9 +90,9 @@ class ToolContext for m in messages do if opt_no_color.value then - stderr.write("{m}\n") + sys.stderr.write("{m}\n") else - stderr.write("{m.to_color_string}\n") + sys.stderr.write("{m.to_color_string}\n") end end @@ -133,6 +134,33 @@ class ToolContext end end + # Executes a program while checking if it's available and if the execution ended correctly + # + # Stops execution and prints errors if the program isn't available or didn't end correctly + fun exec_and_check(args: Array[String], error: String) + do + var prog = args.first + args.remove_at 0 + + # Is the wanted program available? + var proc_which = new IProcess.from_a("which", [prog]) + proc_which.wait + var res = proc_which.status + if res != 0 then + print "{error}: executable \"{prog}\" not found" + exit 1 + end + + # Execute the wanted program + var proc = new Process.from_a(prog, args) + proc.wait + res = proc.status + if res != 0 then + print "{error}: execution of \"{prog} {args.join(" ")}\" failed" + exit 1 + end + end + # Global OptionContext var option_context: OptionContext = new OptionContext @@ -179,7 +207,15 @@ class ToolContext # eg. `"Usage: tool [OPTION]... [FILE]...\nDo some things."` var tooldescription: String writable = "Usage: [OPTION]... [ARG]..." + # Does `process_options` should accept an empty sequence of arguments. + # ie. nothing except options. + # Is `false` by default. + # + # If required, if should be set by the client before calling `process_options` + var accept_no_arguments writable = false + # print the full usage of the tool. + # Is called by `process_option` on `--help`. # It also could be called by the client. fun usage do @@ -188,13 +224,37 @@ class ToolContext end # Parse and process the options given on the command line - fun process_options + fun process_options(args: Sequence[String]) do self.opt_warn.value = 1 # init options option_context.parse(args) + if opt_help.value then + usage + exit 0 + end + + if opt_version.value then + print nit_version + exit 0 + end + + var errors = option_context.get_errors + if not errors.is_empty then + for e in errors do print "Error: {e}" + print tooldescription + print "Use --help for help" + exit 1 + end + + if option_context.rest.is_empty and not accept_no_arguments then + print tooldescription + print "Use --help for help" + exit 1 + end + # Set verbose level verbose_level = opt_verbose.value @@ -205,5 +265,31 @@ class ToolContext # Make sure the output directory exists log_directory.mkdir end + + nit_dir = compute_nit_dir + end + + # The identified root directory of the Nit project + var nit_dir: nullable String + + private fun compute_nit_dir: nullable String + do + # a environ variable has precedence + var res = "NIT_DIR".environ + if not res.is_empty then return res + + # find the runpath of the program from argv[0] + res = "{sys.program_name.dirname}/.." + if res.file_exists and "{res}/src/nit.nit".file_exists then return res.simplify_path + + # find the runpath of the process from /proc + var exe = "/proc/self/exe" + if exe.file_exists then + res = exe.realpath + res = res.dirname.join_path("..") + if res.file_exists and "{res}/src/nit.nit".file_exists then return res.simplify_path + end + + return null end end