1
1
const builtin = @import ("builtin" );
2
2
const std = @import ("std" );
3
+ const mem = std .mem ;
4
+ const io = std .io ;
3
5
const Allocator = std .mem .Allocator ;
4
6
const assert = std .debug .assert ;
5
7
8
+ fn usage () noreturn {
9
+ io .getStdOut ().writeAll (
10
+ \\Usage: zig std [options]
11
+ \\
12
+ \\Options:
13
+ \\ -h, --help Print this help and exit
14
+ \\ -p [port], --port [port] Port to listen on. Default is 0, meaning an ephemeral port chosen by the system.
15
+ \\ --[no-]open-browser Force enabling or disabling opening a browser tab to the served website.
16
+ \\ By default, enabled unless a port is specified.
17
+ \\
18
+ ) catch {};
19
+ std .process .exit (1 );
20
+ }
21
+
6
22
pub fn main () ! void {
7
23
var arena_instance = std .heap .ArenaAllocator .init (std .heap .page_allocator );
8
24
defer arena_instance .deinit ();
@@ -11,23 +27,47 @@ pub fn main() !void {
11
27
var general_purpose_allocator : std .heap .GeneralPurposeAllocator (.{}) = .{};
12
28
const gpa = general_purpose_allocator .allocator ();
13
29
14
- const args = try std .process .argsAlloc (arena );
15
- const zig_lib_directory = args [1 ];
16
- const zig_exe_path = args [2 ];
17
- const global_cache_path = args [3 ];
30
+ var argv = try std .process .argsWithAllocator (arena );
31
+ defer argv .deinit ();
32
+ assert (argv .skip ());
33
+ const zig_lib_directory = argv .next ().? ;
34
+ const zig_exe_path = argv .next ().? ;
35
+ const global_cache_path = argv .next ().? ;
18
36
19
37
var lib_dir = try std .fs .cwd ().openDir (zig_lib_directory , .{});
20
38
defer lib_dir .close ();
21
39
22
- const listen_port : u16 = 0 ;
40
+ var listen_port : u16 = 0 ;
41
+ var force_open_browser : ? bool = null ;
42
+ while (argv .next ()) | arg | {
43
+ if (mem .eql (u8 , arg , "-h" ) or mem .eql (u8 , arg , "--help" )) {
44
+ usage ();
45
+ } else if (mem .eql (u8 , arg , "-p" ) or mem .eql (u8 , arg , "--port" )) {
46
+ listen_port = std .fmt .parseInt (u16 , argv .next () orelse usage (), 10 ) catch | err | {
47
+ std .log .err ("expected port number: {}" , .{err });
48
+ usage ();
49
+ };
50
+ } else if (mem .eql (u8 , arg , "--open-browser" )) {
51
+ force_open_browser = true ;
52
+ } else if (mem .eql (u8 , arg , "--no-open-browser" )) {
53
+ force_open_browser = false ;
54
+ } else {
55
+ std .log .err ("unrecognized argument: {s}" , .{arg });
56
+ usage ();
57
+ }
58
+ }
59
+ const should_open_browser = force_open_browser orelse (listen_port == 0 );
60
+
23
61
const address = std .net .Address .parseIp ("127.0.0.1" , listen_port ) catch unreachable ;
24
62
var http_server = try address .listen (.{});
25
63
const port = http_server .listen_address .in .getPort ();
26
- const url = try std .fmt .allocPrint (arena , "http://127.0.0.1:{d}/\n " , .{port });
27
- std .io .getStdOut ().writeAll (url ) catch {};
28
- openBrowserTab (gpa , url [0 .. url .len - 1 :'\n ' ]) catch | err | {
29
- std .log .err ("unable to open browser: {s}" , .{@errorName (err )});
30
- };
64
+ const url_with_newline = try std .fmt .allocPrint (arena , "http://127.0.0.1:{d}/\n " , .{port });
65
+ std .io .getStdOut ().writeAll (url_with_newline ) catch {};
66
+ if (should_open_browser ) {
67
+ openBrowserTab (gpa , url_with_newline [0 .. url_with_newline .len - 1 :'\n ' ]) catch | err | {
68
+ std .log .err ("unable to open browser: {s}" , .{@errorName (err )});
69
+ };
70
+ }
31
71
32
72
var context : Context = .{
33
73
.gpa = gpa ,
0 commit comments