import opts
import location
+import version
class Message
super Comparable
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
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
option_context.add_option(opt_warn, opt_quiet, opt_stop_on_first_error, opt_no_color, opt_log, opt_log_dir, opt_help, opt_version, opt_verbose)
end
+ # Name, usage and synopsis of the tool.
+ # It is mainly used in `usage`.
+ # Should be correctly set by the client before calling `process_options`
+ # A multi-line string is recommmended.
+ #
+ # 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
+ print tooldescription
+ option_context.usage
+ 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
# 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