aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Colin McDonnell <colinmcd94@gmail.com> 2023-09-29 21:42:25 -0700
committerGravatar Colin McDonnell <colinmcd94@gmail.com> 2023-10-12 16:02:34 -0700
commit2b661aa52bcc0a85c1d5a84d7cb0bd934ee420cf (patch)
tree30cf82faa11b1b07462f6279e44dabc377890b40
parent3cd555210cae15d39e5b615a79f1ecad9de71861 (diff)
downloadbun-2b661aa52bcc0a85c1d5a84d7cb0bd934ee420cf.tar.gz
bun-2b661aa52bcc0a85c1d5a84d7cb0bd934ee420cf.tar.zst
bun-2b661aa52bcc0a85c1d5a84d7cb0bd934ee420cf.zip
WIP
-rw-r--r--src/cli.zig165
-rw-r--r--src/deps/zig-clap/clap/comptime.zig3
-rw-r--r--src/deps/zig-clap/clap/streaming.zig28
3 files changed, 147 insertions, 49 deletions
diff --git a/src/cli.zig b/src/cli.zig
index 46b758a9b..baa6114aa 100644
--- a/src/cli.zig
+++ b/src/cli.zig
@@ -53,7 +53,6 @@ pub const Cli = struct {
var panicker = MainPanicHandler.init(log);
MainPanicHandler.Singleton = &panicker;
-
Command.start(allocator, log) catch |err| {
switch (err) {
error.MissingEntryPoint => {
@@ -167,7 +166,7 @@ pub const Arguments = struct {
pub const ParamType = clap.Param(clap.Help);
const shared_public_params = [_]ParamType{
- clap.parseParam("-h, --help Display this help and exit.") catch unreachable,
+ clap.parseParam("-h, --help") catch unreachable,
clap.parseParam("-b, --bun Force a script or package to use Bun's runtime instead of Node.js (via symlinking node)") catch unreachable,
clap.parseParam("--cwd <STR> Absolute path to resolve files & entry points from. This just changes the process' cwd.") catch unreachable,
clap.parseParam("-c, --config <PATH>? Config file to load Bun from (e.g. -c bunfig.toml") catch unreachable,
@@ -241,14 +240,14 @@ pub const Arguments = struct {
// TODO: update test completions
const test_only_params = [_]ParamType{
- clap.parseParam("--timeout <NUMBER> Set the per-test timeout in milliseconds, default is 5000.") catch unreachable,
- clap.parseParam("--update-snapshots Update snapshot files") catch unreachable,
- clap.parseParam("--rerun-each <NUMBER> Re-run each test file <NUMBER> times, helps catch certain bugs") catch unreachable,
- clap.parseParam("--only Only run tests that are marked with \"test.only()\"") catch unreachable,
- clap.parseParam("--todo Include tests that are marked with \"test.todo()\"") catch unreachable,
- clap.parseParam("--coverage Generate a coverage profile") catch unreachable,
- clap.parseParam("--bail <NUMBER>? Exit the test suite after <NUMBER> failures. If you do not specify a number, it defaults to 1.") catch unreachable,
- clap.parseParam("-t, --test-name-pattern <STR> Run only tests with a name that matches the given regex.") catch unreachable,
+ clap.parseParam("--timeout <NUMBER>") catch unreachable,
+ clap.parseParam("--update-snapshots") catch unreachable,
+ clap.parseParam("--rerun-each <NUMBER>") catch unreachable,
+ clap.parseParam("--only") catch unreachable,
+ clap.parseParam("--todo") catch unreachable,
+ clap.parseParam("--coverage") catch unreachable,
+ clap.parseParam("--bail <NUMBER>?") catch unreachable,
+ clap.parseParam("-t, --test-name-pattern <STR>") catch unreachable,
};
const build_params_public = public_params ++ build_only_params;
@@ -588,10 +587,11 @@ pub const Arguments = struct {
if (print_help) {
std.debug.print("printing help\n", .{});
- clap.help(Output.writer(), params_to_use[0..params_to_use.len]) catch {};
- Output.prettyln("\n-------\n\n", .{});
+ cmd.print_helptext();
+ // clap.help(Output.writer(), params_to_use[0..params_to_use.len]) catch {};
+ // Output.prettyln("\n-------\n\n", .{});
Output.flush();
- HelpCommand.printWithReason(.explicit);
+ // HelpCommand.printWithReason(.explicit);
Global.exit(0);
}
@@ -894,35 +894,35 @@ pub const HelpCommand = struct {
"elysia",
};
- pub fn printWithReason(comptime reason: Reason) void {
- // the spacing between commands here is intentional
- const fmt =
- \\ <b><magenta>run<r> <d>./my-script.ts<r> Run JavaScript with Bun, a package.json script, or a bin
- \\ <b><magenta>test<r> Run unit tests with Bun
- \\ <b><magenta>x<r> <d>{s:<16}<r> Install and execute a package bin <d>(bunx)<r>
- \\ <b><magenta>repl<r> Start a REPL session with Bun
- \\
- \\ <b><cyan>init<r> Start an empty Bun project from a blank template
- \\ <b><cyan>create<r> <d>{s:<16}<r> Create a new project from a template <d>(bun c)<r>
- \\
- \\ <b><blue>install<r> Install dependencies for a package.json <d>(bun i)<r>
- \\ <b><blue>add<r> <d>{s:<16}<r> Add a dependency to package.json <d>(bun a)<r>
- \\ <b><blue>remove<r> <d>{s:<16}<r> Remove a dependency from package.json <d>(bun rm)<r>
- \\ <b><blue>update<r> <d>{s:<16}<r> Update outdated dependencies
- \\ <b><blue>link<r> Link an npm package globally
- \\ <b><blue>unlink<r> Globally unlink an npm package
- \\ <b>pm<r> More commands for managing packages
- \\
- \\ <b><green>build<r> <d>./a.ts ./b.jsx<r> Bundle TypeScript & JavaScript into a single file
- \\
- \\ <b><yellow>upgrade<r> Get the latest version of Bun
- \\ <b>bun --help<r> Show all supported flags and commands
- \\
- \\ Learn more about Bun: <magenta>https://bun.sh/docs<r>
- \\ Join our Discord community: <blue>https://bun.sh/discord<r>
- \\
- ;
+ // the spacing between commands here is intentional
+ pub const cli_helptext_fmt =
+ \\ <b><magenta>run<r> <d>./my-script.ts<r> Run JavaScript with Bun, a package.json script, or a bin
+ \\ <b><magenta>test<r> Run unit tests with Bun
+ \\ <b><magenta>x<r> <d>{s:<16}<r> Install and execute a package bin <d>(bunx)<r>
+ \\ <b><magenta>repl<r> Start a REPL session with Bun
+ \\
+ \\ <b><cyan>init<r> Start an empty Bun project from a blank template
+ \\ <b><cyan>create<r> <d>{s:<16}<r> Create a new project from a template <d>(bun c)<r>
+ \\
+ \\ <b><blue>install<r> Install dependencies for a package.json <d>(bun i)<r>
+ \\ <b><blue>add<r> <d>{s:<16}<r> Add a dependency to package.json <d>(bun a)<r>
+ \\ <b><blue>remove<r> <d>{s:<16}<r> Remove a dependency from package.json <d>(bun rm)<r>
+ \\ <b><blue>update<r> <d>{s:<16}<r> Update outdated dependencies
+ \\ <b><blue>link<r> Link an npm package globally
+ \\ <b><blue>unlink<r> Globally unlink an npm package
+ \\ <b>pm<r> More commands for managing packages
+ \\
+ \\ <b><green>build<r> <d>./a.ts ./b.jsx<r> Bundle TypeScript & JavaScript into a single file
+ \\
+ \\ <b><yellow>upgrade<r> Get the latest version of Bun
+ \\ <b>bun --help<r> Show all supported flags and commands
+ \\
+ \\ Learn more about Bun: <magenta>https://bun.sh/docs<r>
+ \\ Join our Discord community: <blue>https://bun.sh/discord<r>
+ \\
+ ;
+ pub fn printWithReason(comptime reason: Reason) void {
var rand_state = std.rand.DefaultPrng.init(@as(u64, @intCast(@max(std.time.milliTimestamp(), 0))));
const rand = rand_state.random();
@@ -941,11 +941,11 @@ pub const HelpCommand = struct {
switch (reason) {
.explicit => Output.pretty(
- "<r><b><magenta>Bun<r>: a fast JavaScript runtime, package manager, bundler and test runner. <d>(" ++ Global.package_json_version ++ ")<r>\n\n" ++ fmt,
+ "<r><b><magenta>Bun<r>: a fast JavaScript runtime, package manager, bundler and test runner. <d>(" ++ Global.package_json_version ++ ")<r>\n\n" ++ cli_helptext_fmt,
args,
),
.invalid_command => Output.prettyError(
- "<r><red>Uh-oh<r> not sure what to do with that command.\n\n" ++ fmt,
+ "<r><red>Uh-oh<r> not sure what to do with that command.\n\n" ++ cli_helptext_fmt,
args,
),
}
@@ -1090,7 +1090,6 @@ pub const Command = struct {
} else {
std.debug.print("doesnt use global options\n", .{});
}
-
return ctx;
}
};
@@ -1586,8 +1585,10 @@ pub const Command = struct {
return;
},
.AutoCommand => {
+ std.debug.print("running autocommand\n", .{});
if (comptime bun.fast_debug_build_mode and bun.fast_debug_build_cmd != .AutoCommand) unreachable;
var ctx = Command.Context.create(allocator, log, .AutoCommand) catch |e| {
+ std.debug.print("error in context.create()\n", .{});
switch (e) {
error.MissingEntryPoint => {
std.debug.print("missing entry point\n", .{});
@@ -1698,7 +1699,9 @@ pub const Command = struct {
Global.exit(1);
}
- std.debug.print("fallback to help\n", .{});
+ // Output.prettyWarnln("<r><yellow>warn<r><d>:<r> failed to parse command\n", .{});
+ // std.debug.print("fallback to help\n", .{});
+ // Output.flush();
try HelpCommand.exec(allocator);
},
else => unreachable,
@@ -1809,6 +1812,78 @@ pub const Command = struct {
};
}
+ pub fn print_helptext(cmd: Tag) void {
+ return switch (cmd) {
+ Command.Tag.BuildCommand => {
+ const build_helptext =
+ \\<b>Usage<r>: <b><green>bun build<r> [flags] [...entrypoints]
+ \\
+ \\<b>Flags:<r>
+ \\ <cyan>--outfile<r> Write the output to a specific file (default: stdout)
+ \\ <cyan>--outdir<r> Write the output to a directory (required for splitting)
+ \\ <cyan>--minify<r> Enable all minification flags
+ \\ <cyan>--minify-whitespace<r> Remove unneeded whitespace
+ \\ <cyan>--minify-syntax<r> Transform code to use less syntax
+ \\ <cyan>--minify-identifiers<r> Shorten variable names
+ \\ <cyan>--sourcemap<r> Generate sourcemaps
+ \\ ("none", "inline", or "external")
+ \\ <cyan>--target<r> The intended execution environment for the bundle.
+ \\ ("browser", "bun" or "node")
+ \\ <cyan>--splitting<r> Enable code splitting (requires --outdir)
+ \\ <cyan>--watch<r> Run bundler in watch mode
+ \\
+ \\<b>Examples:<r>
+ \\ <d>Frontend web apps:<r>
+ \\ <b><green>bun build<r> <blue>./src/index.ts<r> <cyan>--outfile=bundle.js<r>
+ \\ <b><green>bun build<r> <cyan>--minify<r> <cyan>--splitting<r> <cyan>--outdir=out<r> <blue>./index.jsx ./lib/worker.ts<r>
+ \\
+ \\ <d>Bundle code to be run in Bun (reduces server startup time)<r>
+ \\ <b><green>bun build<r> <cyan>--target=bun<r> <blue>./server.ts<r> <cyan>--outfile=server.js<r>
+ \\
+ \\ <d>Creating a standalone executable (see https://bun.sh/docs/bundler/executables)<r>
+ \\ <b><green>bun build<r> <cyan>--compile<r> <blue>./cli.ts<r> <cyan>--outfile=my-app<r>
+ \\
+ \\Run `bun build --help --all` A full list of flags is available at <magenta>https://bun.sh/docs/bundler<r>
+ ;
+ Output.pretty(build_helptext, .{});
+ Output.flush();
+ },
+ Command.Tag.TestCommand => {
+ const test_helptext =
+ \\<b>Usage<r>: <b><green>bun test<r> [flags] [patterns...]
+ \\ Run all matching test files and print the results to stdout
+ \\
+ \\<b>Flags:<r>
+ \\ <cyan> --timeout N<r> Set the per-test timeout in milliseconds. Default 5000.
+ \\ <cyan> --update-snapshots<r> Update snapshot files
+ \\ <cyan> --rerun-each N<r> Re-run each test file N times, helps catch certain bugs
+ \\ <cyan> --only<r> Only run tests that are marked with "test.only()"
+ \\ <cyan> --todo<r> Include tests that are marked with "test.todo()"
+ \\ <cyan> --coverage<r> Generate a coverage profile
+ \\ <cyan> --bail [N]<r> Exit the test suite after N failures. Default 1.
+ \\ <cyan>-t, --test-name-pattern [patterns...]<r> Run only tests with a name that matches the given regex.
+ \\
+ \\<b>Examples:<r>
+ \\ <d>Run all test files <r>
+ \\ <b><green>bun test<r>
+ \\
+ \\ <d>Run all test files with "foo" or "bar" in the file name<r>
+ \\ <b><green>bun test foo bar<r>
+ \\
+ \\ <d>Run all test files, only including tests whose names includes "baz"<r>
+ \\ <b><green>bun test<r> <cyan>--test-name-pattern<r> baz<r>
+ \\
+ \\Run `bun test --help --all` A full list of flags is available at <magenta>https://bun.sh/docs/bundler<r>
+ ;
+ Output.pretty(test_helptext, .{});
+ Output.flush();
+ },
+ else => {
+ HelpCommand.printWithReason(.explicit);
+ },
+ };
+ }
+
pub fn readGlobalConfig(this: Tag) bool {
return switch (this) {
.BunxCommand, .PackageManagerCommand, .InstallCommand, .AddCommand, .RemoveCommand, .UpdateCommand => true,
diff --git a/src/deps/zig-clap/clap/comptime.zig b/src/deps/zig-clap/clap/comptime.zig
index d32a60f11..a890ee4e2 100644
--- a/src/deps/zig-clap/clap/comptime.zig
+++ b/src/deps/zig-clap/clap/comptime.zig
@@ -74,6 +74,9 @@ pub fn ComptimeClap(
while (try stream.next()) |arg| {
const param = arg.param;
+ // std.debug.print("arg: {s}\n", .{arg.value orelse "~null~"});
+ // std.debug.print("arg: {s}\n", .{arg.param.names.long orelse arg.param.names.short orelse "~noname~"});
+ // std.debug.print("state: {s}\n", .{@tagName(stream.state)});
if (param.names.long == null and param.names.short == null) {
try pos.append(arg.value.?);
if (opt.stop_after_positional_at > 0 and pos.items.len >= opt.stop_after_positional_at) {
diff --git a/src/deps/zig-clap/clap/streaming.zig b/src/deps/zig-clap/clap/streaming.zig
index 1611a41ae..0e5d24ad8 100644
--- a/src/deps/zig-clap/clap/streaming.zig
+++ b/src/deps/zig-clap/clap/streaming.zig
@@ -1,6 +1,7 @@
const builtin = @import("builtin");
const clap = @import("../clap.zig");
const std = @import("std");
+const Output = @import("../../../output.zig");
const args = clap.args;
const debug = std.debug;
@@ -36,6 +37,8 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
};
};
+ const ArgError = error{ DoesntTakeValue, MissingValue, InvalidArgument };
+
params: []const clap.Param(Id),
iter: *ArgIterator,
state: State = .normal,
@@ -43,7 +46,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
diagnostic: ?*clap.Diagnostic = null,
/// Get the next Arg that matches a Param.
- pub fn next(parser: *@This()) !?Arg(Id) {
+ pub fn next(parser: *@This()) ArgError!?Arg(Id) {
switch (parser.state) {
.normal => return try parser.normal(),
.chaining => |state| return try parser.chainging(state),
@@ -55,15 +58,19 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
}
}
- fn normal(parser: *@This()) !?Arg(Id) {
+ fn normal(parser: *@This()) ArgError!?Arg(Id) {
+ std.debug.print("normal()\n", .{});
const ArgType = Arg(Id);
const arg_info = (try parser.parseNextArg()) orelse return null;
const arg = arg_info.arg;
+ std.debug.print("arg: {s}:{s}\n", .{ arg, @tagName(arg_info.kind) });
+
switch (arg_info.kind) {
.long => {
const eql_index = mem.indexOfScalar(u8, arg, '=');
const name = if (eql_index) |i| arg[0..i] else arg;
+
const maybe_value = if (eql_index) |i| arg[i + 1 ..] else null;
for (parser.params) |*param| {
@@ -92,6 +99,17 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
return ArgType{ .param = param, .value = value };
}
+ // unrecognized command
+ // if flag else arg
+ if (arg_info.kind == .long or arg_info.kind == .short) {
+ Output.prettyWarnln("<r><yellow>warn<r><d>:<r> unrecognized flag: {s}{s}\n", .{ if (arg_info.kind == .long) "--" else "-", name });
+ Output.flush();
+ // continue parsing after unrecognized flag
+ return parser.next();
+ }
+
+ Output.prettyWarnln("<r><yellow>warn<r><d>:<r> unrecognized argument: {s}\n", .{name});
+ Output.flush();
return null;
},
.short => return try parser.chainging(.{
@@ -103,7 +121,9 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
// interpret the rest of the arguments as positional
// arguments.
if (mem.eql(u8, arg, "--")) {
+ std.debug.print("rest are positional\n", .{});
parser.state = .rest_are_positional;
+ // return null to terminate arg parsing
const value = parser.iter.next() orelse return null;
return Arg(Id){ .param = param, .value = value };
}
@@ -115,7 +135,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
}
}
- fn chainging(parser: *@This(), state: State.Chaining) !?Arg(Id) {
+ fn chainging(parser: *@This(), state: State.Chaining) ArgError!?Arg(Id) {
const arg = state.arg;
const index = state.index;
const next_index = index + 1;
@@ -188,7 +208,7 @@ pub fn StreamingClap(comptime Id: type, comptime ArgIterator: type) type {
},
};
- fn parseNextArg(parser: *@This()) !?ArgInfo {
+ fn parseNextArg(parser: *@This()) ArgError!?ArgInfo {
const full_arg = parser.iter.next() orelse return null;
if (mem.eql(u8, full_arg, "--") or mem.eql(u8, full_arg, "-"))
return ArgInfo{ .arg = full_arg, .kind = .positional };