aboutsummaryrefslogtreecommitdiff
path: root/src/cli/run_command.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli/run_command.zig')
-rw-r--r--src/cli/run_command.zig112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/cli/run_command.zig b/src/cli/run_command.zig
index fba8296a8..60688e5a9 100644
--- a/src/cli/run_command.zig
+++ b/src/cli/run_command.zig
@@ -33,6 +33,8 @@ const NpmArgs = struct {
const yarn_commands: []u64 = @import("./list-of-yarn-commands.zig").all_yarn_commands;
+const ShellCompletions = @import("./shell_completions.zig");
+
pub const RunCommand = struct {
const shells_to_search = &[_]string{
"bash",
@@ -267,6 +269,116 @@ pub const RunCommand = struct {
this_bundler.configureLinker();
}
+ pub const Filter = enum {
+ script,
+ bin,
+ all,
+ };
+
+ pub fn completions(ctx: Command.Context, default_completions: ?[]const string, comptime filter: Filter) !ShellCompletions {
+ var shell_out = ShellCompletions{};
+
+ if (default_completions) |defaults| {
+ shell_out.commands = defaults;
+ }
+
+ var args = ctx.args;
+ args.node_modules_bundle_path = null;
+ args.node_modules_bundle_path_server = null;
+ args.generate_node_module_bundle = false;
+
+ var this_bundler = bundler.Bundler.init(ctx.allocator, ctx.log, args, null, null) catch return shell_out;
+ this_bundler.options.env.behavior = Api.DotEnvBehavior.load_all;
+ this_bundler.options.env.prefix = "";
+ this_bundler.env.quiet = true;
+
+ this_bundler.resolver.care_about_bin_folder = true;
+ this_bundler.resolver.care_about_scripts = true;
+ defer {
+ this_bundler.resolver.care_about_bin_folder = false;
+ this_bundler.resolver.care_about_scripts = false;
+ }
+ this_bundler.configureLinker();
+
+ var root_dir_info = (this_bundler.resolver.readDirInfo(this_bundler.fs.top_level_dir) catch null) orelse return shell_out;
+
+ {
+ this_bundler.env.loadProcess();
+
+ if (this_bundler.env.map.get("NODE_ENV")) |node_env| {
+ if (strings.eqlComptime(node_env, "production")) {
+ this_bundler.options.production = true;
+ }
+ }
+ }
+
+ const ResultList = std.StringArrayHashMap(void);
+
+ if (this_bundler.env.map.get("SHELL")) |shell| {
+ shell_out.shell = ShellCompletions.Shell.fromEnv(@TypeOf(shell), shell);
+ }
+
+ var results = ResultList.init(ctx.allocator);
+
+ if (default_completions) |defaults| {
+ try results.ensureUnusedCapacity(defaults.len);
+ for (defaults) |item| {
+ _ = results.getOrPutAssumeCapacity(item);
+ }
+ }
+
+ if (filter == Filter.bin or filter == Filter.all) {
+ for (this_bundler.resolver.binDirs()) |bin_path| {
+ if (this_bundler.resolver.readDirInfo(bin_path) catch null) |bin_dir| {
+ if (bin_dir.getEntriesConst()) |entries| {
+ var iter = entries.data.iterator();
+ var has_copied = false;
+ var path_slice: string = "";
+ var dir_slice: string = "";
+ while (iter.next()) |entry| {
+ if (entry.value.kind(&this_bundler.fs.fs) == .file) {
+ if (!has_copied) {
+ std.mem.copy(u8, &path_buf, entry.value.dir);
+ dir_slice = path_buf[0..entry.value.dir.len];
+ if (!strings.endsWithChar(entry.value.dir, std.fs.path.sep)) {
+ dir_slice = path_buf[0 .. entry.value.dir.len + 1];
+ }
+ has_copied = true;
+ }
+
+ const base = entry.value.base();
+ std.mem.copy(u8, path_buf[dir_slice.len..], base);
+ path_buf[dir_slice.len + base.len] = 0;
+ var slice = path_buf[0 .. dir_slice.len + base.len :0];
+ std.os.accessZ(slice, std.os.X_OK) catch continue;
+ // we need to dupe because the string pay point to a pointer that only exists in the current scope
+ _ = try results.getOrPut(this_bundler.fs.filename_store.append(@TypeOf(base), base) catch continue);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (filter == Filter.script or filter == Filter.all) {
+ if (root_dir_info.enclosing_package_json) |package_json| {
+ if (package_json.scripts) |scripts| {
+ try results.ensureUnusedCapacity(scripts.count());
+ for (scripts.keys()) |key| {
+ _ = results.getOrPutAssumeCapacity(key);
+ }
+ }
+ }
+ }
+
+ var all_keys = results.keys();
+
+ strings.sortAsc(all_keys);
+ shell_out.commands = all_keys;
+
+ return shell_out;
+ }
+
pub fn exec(ctx: Command.Context, comptime bin_dirs_only: bool, comptime log_errors: bool) !bool {
// Step 1. Figure out what we're trying to run
var positionals = ctx.positionals;