diff --git a/.gitignore b/.gitignore index 44415db..01cb47e 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,6 @@ envr-prof findr/findr findr/findr-prof findr/bench-*.md +gendocs result version.odin diff --git a/TODOS.md b/TODOS.md index 2dfc257..71ce749 100644 --- a/TODOS.md +++ b/TODOS.md @@ -8,8 +8,6 @@ 4. Test all command branches. -5. Generate md and man pages again. - 6. Add tests for untested commands. 7. Add purge command? diff --git a/cli.odin b/cli.odin index 86458e4..df0616f 100644 --- a/cli.odin +++ b/cli.odin @@ -52,6 +52,7 @@ Positional_Arg :: struct { ntype: string, // nushell type: "path", "string". "" defaults to "path" completion: string, optional: bool, + desc: string, } CommandInfo :: struct { @@ -96,14 +97,14 @@ key somewhere, otherwise your data could be lost forever.`, short = "Import a .env file into envr", aliases = {"add"}, flags = GLOBAL_FLAGS, - args = {{name = "path", completion = "untracked-paths"}}, + args = {{name = "path", completion = "untracked-paths", desc = "Path to .env file to backup"}}, }, { name = "restore", usage = "envr restore ", short = "Restore a .env file from the database", flags = GLOBAL_FLAGS, - args = {{name = "path", completion = "tracked-paths"}}, + args = {{name = "path", completion = "tracked-paths", desc = "Path to .env file to restore"}}, }, { name = "list", @@ -116,14 +117,14 @@ key somewhere, otherwise your data could be lost forever.`, usage = "envr remove ", short = "Remove a .env file from your database", flags = GLOBAL_FLAGS, - args = {{name = "path", completion = "tracked-paths"}}, + args = {{name = "path", completion = "tracked-paths", desc = "Path to .env file to remove"}}, }, { name = "check", usage = "envr check [path]", short = "Check if files are backed up", flags = GLOBAL_FLAGS, - args = {{name = "path", optional = true}}, + args = {{name = "path", optional = true, desc = "Path to check (defaults to current directory)"}}, }, {name = "version", usage = "envr version", short = "Show envr's version", flags = {.Help}}, { @@ -141,7 +142,7 @@ key somewhere, otherwise your data could be lost forever.`, nushell bash`, flags = {.Help}, - args = {{name = "shell", ntype = "string", completion = "shells"}}, + args = {{name = "shell", ntype = "string", completion = "shells", desc = "Shell to generate completions for"}}, }, { name = "uninstall", @@ -387,11 +388,7 @@ find_command :: proc(name: string) -> (CommandInfo, bool) { return CommandInfo{}, false } -// TODO: command args should be shown in usage. -write_usage :: proc(w: io.Writer) { - fmt.wprintf( - w, - `envr keeps your .env synced to a local, encrypted database. +ENVR_DESCRIPTION :: `envr keeps your .env synced to a local, encrypted database. Is a safe and easy way to gather all your .env files in one place where they can easily be backed by another tool such as restic or git. @@ -420,13 +417,14 @@ Select the files you want to back up from the interactive list. 5. If you lose a repository, after re-cloning the repo into the same path it was at before, restore your backup with: -> envr restore ~//.env +> envr restore ~//.env` -%s - - %s [command] - -`, +// TODO: command args should be shown in usage. +write_usage :: proc(w: io.Writer) { + fmt.wprintf( + w, + "%s\n\n%s\n\n %s [command]\n\n", + ENVR_DESCRIPTION, colorize(.Heading, "Usage:"), colorize(.Flag, "envr"), flush = false, diff --git a/docs/cli/envr.md b/docs/cli/envr.md index 96fb938..af7212b 100644 --- a/docs/cli/envr.md +++ b/docs/cli/envr.md @@ -5,7 +5,7 @@ Manage your .env files. ### Synopsis envr keeps your .env synced to a local, encrypted database. -Is a safe and eay way to gather all your .env files in one place where they can +Is a safe and easy way to gather all your .env files in one place where they can easily be backed by another tool such as restic or git. All your data is stored in ~/.envr/data.envr @@ -33,25 +33,26 @@ Select the files you want to back up from the interactive list. 5. If you lose a repository, after re-cloning the repo into the same path it was at before, restore your backup with: -> envr restore ~/<path to repository>/.env +> envr restore ~//.env ### Options ``` - -h, --help help for envr + -h, --help show this documentation ``` ### SEE ALSO -* [envr backup](envr_backup.md) - Import a .env file into envr -* [envr check](envr_check.md) - check if files in the current directory are backed up -* [envr edit-config](envr_edit-config.md) - Edit your config with your default editor * [envr init](envr_init.md) - Set up envr -* [envr list](envr_list.md) - View your tracked files -* [envr nushell-completion](envr_nushell-completion.md) - Generate custom completions for nushell -* [envr remove](envr_remove.md) - Remove a .env file from your database -* [envr restore](envr_restore.md) - Install a .env file from the database into your file system * [envr scan](envr_scan.md) - Find and select .env files for backup * [envr sync](envr_sync.md) - Update or restore your env backups +* [envr backup](envr_backup.md) - Import a .env file into envr +* [envr restore](envr_restore.md) - Restore a .env file from the database +* [envr list](envr_list.md) - View your tracked files +* [envr remove](envr_remove.md) - Remove a .env file from your database +* [envr check](envr_check.md) - Check if files are backed up * [envr version](envr_version.md) - Show envr's version +* [envr edit-config](envr_edit-config.md) - Edit your config with your default editor +* [envr completion](envr_completion.md) - Generate shell completion scripts +* [envr uninstall](envr_uninstall.md) - Remove envr configuration and database diff --git a/docs/cli/envr_backup.md b/docs/cli/envr_backup.md index 2ebbb7c..1230486 100644 --- a/docs/cli/envr_backup.md +++ b/docs/cli/envr_backup.md @@ -6,13 +6,20 @@ Import a .env file into envr envr backup [flags] ``` +**Arguments:** + +* `path` — Path to .env file to backup + ### Options ``` - -h, --help help for backup + -h, --help show this documentation + -c, --config-file config file (default "~/.envr/config.json") + --color Whether or not to colorize output (default 'auto') ``` +*Alias: `add`* + ### SEE ALSO * [envr](envr.md) - Manage your .env files. - diff --git a/docs/cli/envr_check.md b/docs/cli/envr_check.md index 3b00192..2cb46bf 100644 --- a/docs/cli/envr_check.md +++ b/docs/cli/envr_check.md @@ -1,18 +1,23 @@ ## envr check -check if files in the current directory are backed up +Check if files are backed up ``` envr check [path] [flags] ``` +**Arguments:** + +* `path` — Path to check (defaults to current directory) (optional) + ### Options ``` - -h, --help help for check + -h, --help show this documentation + -c, --config-file config file (default "~/.envr/config.json") + --color Whether or not to colorize output (default 'auto') ``` ### SEE ALSO * [envr](envr.md) - Manage your .env files. - diff --git a/docs/cli/envr_completion.md b/docs/cli/envr_completion.md new file mode 100644 index 0000000..2aae995 --- /dev/null +++ b/docs/cli/envr_completion.md @@ -0,0 +1,28 @@ +## envr completion + +Generate shell completion scripts + +### Synopsis + +Supported shells: + + nushell + bash + +``` +envr completion [flags] +``` + +**Arguments:** + +* `shell` — Shell to generate completions for + +### Options + +``` + -h, --help show this documentation +``` + +### SEE ALSO + +* [envr](envr.md) - Manage your .env files. diff --git a/docs/cli/envr_edit-config.md b/docs/cli/envr_edit-config.md index 8e70d90..b50bc1e 100644 --- a/docs/cli/envr_edit-config.md +++ b/docs/cli/envr_edit-config.md @@ -9,10 +9,11 @@ envr edit-config [flags] ### Options ``` - -h, --help help for edit-config + -h, --help show this documentation + -c, --config-file config file (default "~/.envr/config.json") + --color Whether or not to colorize output (default 'auto') ``` ### SEE ALSO * [envr](envr.md) - Manage your .env files. - diff --git a/docs/cli/envr_init.md b/docs/cli/envr_init.md index 83db800..e3c1cb6 100644 --- a/docs/cli/envr_init.md +++ b/docs/cli/envr_init.md @@ -5,9 +5,7 @@ Set up envr ### Synopsis The init command generates your initial config and saves it to -~/.envr/config in JSON format. - -During setup, you will be prompted to select one or more ssh keys with which to +~/.envr/config in JSON format.\n\nDuring setup, you will be prompted to select one or more ssh keys with which to encrypt your databse. **Make 100% sure** that you have **a remote copy** of this key somewhere, otherwise your data could be lost forever. @@ -18,11 +16,12 @@ envr init [flags] ### Options ``` - -f, --force Overwrite an existing config - -h, --help help for init + -h, --help show this documentation + -c, --config-file config file (default "~/.envr/config.json") + --color Whether or not to colorize output (default 'auto') + -f, --force Overwrite existing config ``` ### SEE ALSO * [envr](envr.md) - Manage your .env files. - diff --git a/docs/cli/envr_list.md b/docs/cli/envr_list.md index 7b667e9..fc89258 100644 --- a/docs/cli/envr_list.md +++ b/docs/cli/envr_list.md @@ -9,10 +9,12 @@ envr list [flags] ### Options ``` - -h, --help help for list + -h, --help show this documentation + -c, --config-file config file (default "~/.envr/config.json") + -o, --output the format of output data (default 'table') + --color Whether or not to colorize output (default 'auto') ``` ### SEE ALSO * [envr](envr.md) - Manage your .env files. - diff --git a/docs/cli/envr_nushell-completion.md b/docs/cli/envr_nushell-completion.md deleted file mode 100644 index 7dd6cd0..0000000 --- a/docs/cli/envr_nushell-completion.md +++ /dev/null @@ -1,23 +0,0 @@ -## envr nushell-completion - -Generate custom completions for nushell - -### Synopsis - -At time of writing, cobra does not natively support nushell, -so a custom command had to be written - -``` -envr nushell-completion [flags] -``` - -### Options - -``` - -h, --help help for nushell-completion -``` - -### SEE ALSO - -* [envr](envr.md) - Manage your .env files. - diff --git a/docs/cli/envr_remove.md b/docs/cli/envr_remove.md index fb26a60..a04ff95 100644 --- a/docs/cli/envr_remove.md +++ b/docs/cli/envr_remove.md @@ -3,16 +3,21 @@ Remove a .env file from your database ``` -envr remove [flags] +envr remove [flags] ``` +**Arguments:** + +* `path` — Path to .env file to remove + ### Options ``` - -h, --help help for remove + -h, --help show this documentation + -c, --config-file config file (default "~/.envr/config.json") + --color Whether or not to colorize output (default 'auto') ``` ### SEE ALSO * [envr](envr.md) - Manage your .env files. - diff --git a/docs/cli/envr_restore.md b/docs/cli/envr_restore.md index 3fa947f..d625c72 100644 --- a/docs/cli/envr_restore.md +++ b/docs/cli/envr_restore.md @@ -1,18 +1,23 @@ ## envr restore -Install a .env file from the database into your file system +Restore a .env file from the database ``` -envr restore [flags] +envr restore [flags] ``` +**Arguments:** + +* `path` — Path to .env file to restore + ### Options ``` - -h, --help help for restore + -h, --help show this documentation + -c, --config-file config file (default "~/.envr/config.json") + --color Whether or not to colorize output (default 'auto') ``` ### SEE ALSO * [envr](envr.md) - Manage your .env files. - diff --git a/docs/cli/envr_scan.md b/docs/cli/envr_scan.md index 73c699c..435a0aa 100644 --- a/docs/cli/envr_scan.md +++ b/docs/cli/envr_scan.md @@ -9,10 +9,11 @@ envr scan [flags] ### Options ``` - -h, --help help for scan + -h, --help show this documentation + -c, --config-file config file (default "~/.envr/config.json") + --color Whether or not to colorize output (default 'auto') ``` ### SEE ALSO * [envr](envr.md) - Manage your .env files. - diff --git a/docs/cli/envr_sync.md b/docs/cli/envr_sync.md index cc11cba..e9ec126 100644 --- a/docs/cli/envr_sync.md +++ b/docs/cli/envr_sync.md @@ -9,10 +9,12 @@ envr sync [flags] ### Options ``` - -h, --help help for sync + -h, --help show this documentation + -c, --config-file config file (default "~/.envr/config.json") + -o, --output the format of output data (default 'table') + --color Whether or not to colorize output (default 'auto') ``` ### SEE ALSO * [envr](envr.md) - Manage your .env files. - diff --git a/docs/cli/envr_uninstall.md b/docs/cli/envr_uninstall.md new file mode 100644 index 0000000..7a525d2 --- /dev/null +++ b/docs/cli/envr_uninstall.md @@ -0,0 +1,24 @@ +## envr uninstall + +Remove envr configuration and database + +### Synopsis + +This will remove all files generated by envr from your system. + +``` +envr uninstall [flags] +``` + +### Options + +``` + -h, --help show this documentation + -c, --config-file config file (default "~/.envr/config.json") + --color Whether or not to colorize output (default 'auto') + -f, --force Overwrite existing config +``` + +### SEE ALSO + +* [envr](envr.md) - Manage your .env files. diff --git a/docs/cli/envr_version.md b/docs/cli/envr_version.md index 123968f..084f52f 100644 --- a/docs/cli/envr_version.md +++ b/docs/cli/envr_version.md @@ -9,11 +9,9 @@ envr version [flags] ### Options ``` - -h, --help help for version - -l, --long Show all version information + -h, --help show this documentation ``` ### SEE ALSO * [envr](envr.md) - Manage your .env files. - diff --git a/flake.nix b/flake.nix index d9d1c64..9688a95 100644 --- a/flake.nix +++ b/flake.nix @@ -91,6 +91,11 @@ buildPhase = '' runHook preBuild echo '${version}' > version.txt + + # Generate man pages before main build (binary gets clobbered) + odin build . -define:GENDOCS=true -out:gendocs + ./gendocs --man + odin build . -o:speed -out:${pname} runHook postBuild ''; @@ -98,6 +103,9 @@ installPhase = '' runHook preInstall install -Dm755 ${pname} $out/bin/${pname} + + mkdir -p $out/share/man/man1 + cp docs/man/*.1 $out/share/man/man1/ runHook postInstall ''; }; diff --git a/gendocs.odin b/gendocs.odin new file mode 100644 index 0000000..e5b03b2 --- /dev/null +++ b/gendocs.odin @@ -0,0 +1,289 @@ +package main + +import "core:fmt" +import "core:os" +import "core:strings" +import "core:time" + +when #config(GENDOCS, false) { + main :: proc() { + args := os.args + if len(args) < 2 { + fmt.eprintln("Usage: gendocs --man | --md") + os.exit(1) + } + + switch args[1] { + case "--man": + generate_man_pages() + case "--md": + generate_markdown() + case: + fmt.eprintf("Unknown format: %s\n", args[1]) + os.exit(1) + } + } +} + +generate_man_pages :: proc() { + os.mkdir_all("docs/man") + + now := time.now() + month_year := fmt.tprintf("%s %d", time.month(now), time.year(now)) + + generate_man_main(month_year) + + for &c in COMMANDS { + generate_man_command(&c, month_year) + } + + fmt.println("Generated man pages in docs/man/") +} + +generate_man_main :: proc(month_year: string) { + sb: strings.Builder + strings.builder_init(&sb, context.temp_allocator) + defer strings.builder_destroy(&sb) + + fmt.sbprintf(&sb, ".TH ENVR 1 \"%s\" \"envr\" \"envr Manual\"\n", month_year) + fmt.sbprintf(&sb, ".SH NAME\nenvr \\- keep your .env files synced to an encrypted database\n") + fmt.sbprintf(&sb, ".SH SYNOPSIS\n\\fBenvr\\fR [\\fIcommand\\fR] [\\fIflags\\fR]\n") + fmt.sbprintf( + &sb, + ".SH DESCRIPTION\nenvr keeps your .env synced to a local, encrypted database.\n", + ) + fmt.sbprintf( + &sb, + "Is a safe and easy way to gather all your .env files in one place where they can\n", + ) + fmt.sbprintf(&sb, "easily be backed by another tool such as restic or git.\n") + fmt.sbprintf(&sb, ".PP\nAll your data is stored in ~/.envr/data.envr\n") + fmt.sbprintf(&sb, ".SH COMMANDS\n") + for c in COMMANDS { + fmt.sbprintf(&sb, ".TP\n\\fB%s\\fR\n%s\n", c.name, c.short) + for a in c.aliases { + fmt.sbprintf(&sb, ".TP\n\\fB%s\\fR (alias for %s)\n%s\n", a, c.name, c.short) + } + } + fmt.sbprintf(&sb, ".SH GLOBAL OPTIONS\n") + for ft in Flag_Type { + if ft not_in GLOBAL_FLAGS do continue + write_man_flag(&sb, ft) + } + fmt.sbprintf(&sb, ".SH SEE ALSO\n") + for c, i in COMMANDS { + if i > 0 do fmt.sbprintf(&sb, ",\n") + fmt.sbprintf(&sb, ".BR envr-%s (1)", c.name) + } + fmt.sbprintf(&sb, "\n") + + path := "docs/man/envr.1" + err := os.write_entire_file(path, transmute([]u8)strings.to_string(sb)) + if err != nil { + fmt.eprintf("Error writing %s: %v\n", path, err) + } +} + +generate_man_command :: proc(c: ^CommandInfo, month_year: string) { + sb: strings.Builder + strings.builder_init(&sb, context.temp_allocator) + defer strings.builder_destroy(&sb) + + upper_name := strings.to_upper(fmt.tprintf("envr-%s", c.name)) + + fmt.sbprintf(&sb, ".TH %s 1 \"%s\" \"envr\" \"envr Manual\"\n", upper_name, month_year) + fmt.sbprintf(&sb, ".SH NAME\nenvr-%s \\- %s\n", c.name, c.short) + fmt.sbprintf(&sb, ".SH SYNOPSIS\n\\fB%s\\fR", c.usage) + + has_positionals := false + for arg in c.args { + has_positionals = true + if arg.optional { + fmt.sbprintf(&sb, " [\\fI%s\\fR]", arg.name) + } else { + fmt.sbprintf(&sb, " \\fI%s\\fR", arg.name) + } + } + fmt.sbprintf(&sb, "\n") + + if len(c.long) > 0 { + fmt.sbprintf(&sb, ".SH DESCRIPTION\n%s\n", c.long) + } + + if has_positionals { + fmt.sbprintf(&sb, ".SH ARGUMENTS\n") + for arg in c.args { + fmt.sbprintf(&sb, ".TP\n\\fB%s\\fR\n%s\n", arg.name, arg.desc) + } + } + + fmt.sbprintf(&sb, ".SH OPTIONS\n") + for ft in Flag_Type { + if ft not_in c.flags do continue + write_man_flag(&sb, ft) + } + + path := fmt.tprintf("docs/man/envr-%s.1", c.name) + err := os.write_entire_file(path, transmute([]u8)strings.to_string(sb)) + if err != nil { + fmt.eprintf("Error writing %s: %v\n", path, err) + } +} + +write_man_flag :: proc(sb: ^strings.Builder, ft: Flag_Type) { + f := flag_field(ft) + + fmt.sbprintf(sb, ".TP\n") + if len(f.short_name) > 0 { + fmt.sbprintf(sb, "\\fB-%s\\fR, \\fB--%s\\fR", f.short_name, f.long_name) + } else { + fmt.sbprintf(sb, "\\fB--%s\\fR", f.long_name) + } + + #partial switch f.kind { + case .String: + fmt.sbprintf(sb, " \\fIvalue\\fR") + case .Enum: + values, _ := strings.replace(f.enum_values, "'", "", -1) + fmt.sbprintf(sb, " \\fI%s\\fR", values) + } + + fmt.sbprintf(sb, "\n%s\n", f.usage) + + if len(f.default_val) > 0 { + #partial switch f.kind { + case .String: + fmt.sbprintf(sb, "(default \"%s\")\n", f.default_val) + case .Enum: + fmt.sbprintf(sb, "(default '%s')\n", f.default_val) + } + } +} + +generate_markdown :: proc() { + os.mkdir_all("docs/cli") + + generate_md_main() + + for &c in COMMANDS { + generate_md_command(&c) + } + + fmt.println("Generated markdown in docs/cli/") +} + +generate_md_main :: proc() { + sb: strings.Builder + strings.builder_init(&sb, context.temp_allocator) + defer strings.builder_destroy(&sb) + + fmt.sbprintf(&sb, "## envr\n\n") + fmt.sbprintf(&sb, "Manage your .env files.\n\n") + fmt.sbprintf(&sb, "### Synopsis\n\n") + fmt.sbprint(&sb, ENVR_DESCRIPTION) + fmt.sbprintf(&sb, "\n\n### Options\n\n") + write_md_options(&sb, {.Help}) + fmt.sbprintf(&sb, "\n### SEE ALSO\n\n") + for c in COMMANDS { + fmt.sbprintf(&sb, "* [envr %s](envr_%s.md)\t - %s\n", c.name, c.name, c.short) + } + fmt.sbprintf(&sb, "\n") + + write_file("docs/cli/envr.md", strings.to_string(sb)) +} + +generate_md_command :: proc(c: ^CommandInfo) { + sb: strings.Builder + strings.builder_init(&sb, context.temp_allocator) + defer strings.builder_destroy(&sb) + + fmt.sbprintf(&sb, "## envr %s\n\n", c.name) + fmt.sbprintf(&sb, "%s\n\n", c.short) + + if len(c.long) > 0 { + fmt.sbprintf(&sb, "### Synopsis\n\n") + fmt.sbprint(&sb, c.long) + fmt.sbprintf(&sb, "\n\n") + } + + fmt.sbprintf(&sb, "```\n%s [flags]\n```\n\n", c.usage) + + if len(c.args) > 0 { + fmt.sbprintf(&sb, "**Arguments:**\n\n") + for arg in c.args { + optional := arg.optional ? " (optional)" : "" + fmt.sbprintf(&sb, "* `%s` — %s%s\n", arg.name, arg.desc, optional) + } + fmt.sbprintf(&sb, "\n") + } + + fmt.sbprintf(&sb, "### Options\n\n") + write_md_options(&sb, c.flags) + + for a in c.aliases { + fmt.sbprintf(&sb, "\n*Alias: `%s`*\n", a) + } + + fmt.sbprintf(&sb, "\n### SEE ALSO\n\n") + fmt.sbprintf(&sb, "* [envr](envr.md)\t - Manage your .env files.\n") + + path := fmt.tprintf("docs/cli/envr_%s.md", c.name) + write_file(path, strings.to_string(sb)) +} + +write_md_options :: proc(sb: ^strings.Builder, flags: bit_set[Flag_Type]) { + displays := make([dynamic]string, 0, 5, context.temp_allocator) + defer delete(displays) + + descs := make([dynamic]string, 0, 5, context.temp_allocator) + defer delete(descs) + + max_width := 0 + + for ft in Flag_Type { + if ft not_in flags do continue + f := flag_field(ft) + + display: string + if len(f.short_name) > 0 { + display = fmt.tprintf("-%s, --%s", f.short_name, f.long_name) + } else { + display = fmt.tprintf(" --%s", f.long_name) + } + + desc := f.usage + if len(f.default_val) > 0 { + #partial switch f.kind { + case .String: + desc = fmt.tprintf(`%s (default "%s")`, f.usage, f.default_val) + case .Enum: + desc = fmt.tprintf("%s (default '%s')", f.usage, f.default_val) + } + } + + append(&displays, display) + append(&descs, desc) + if len(display) > max_width { + max_width = len(display) + } + } + + fmt.sbprintf(sb, "```\n") + pad_buf: [64]u8 + for i in 0.. 0 { + for _, leak in heap_track.allocation_map { + fmt.eprintf("LEAK: %v leaked %m\n", leak.location, leak.size) + } + } + context.allocator = mem.tracking_allocator(&heap_track) + + temp_track: mem.Tracking_Allocator + mem.tracking_allocator_init(&temp_track, context.temp_allocator) + defer mem.tracking_allocator_destroy(&temp_track) + context.temp_allocator = mem.tracking_allocator(&temp_track) + } + + defer free_all(context.temp_allocator) + + cmd, ok := parse_args(os.args, os.to_writer(os.stdout), os.to_writer(os.stderr)) + defer delete_command(&cmd) // delete flushes automatically + if !ok { + return + } + + switch cmd.name { + case "init": + cmd_init(&cmd) + case "version": + cmd_version(&cmd) + case "list": + cmd_list(&cmd) + case "backup", "add": + cmd_backup(&cmd) + case "remove": + cmd_remove(&cmd) + case "restore": + cmd_restore(&cmd) + case "edit-config": + cmd_edit_config(&cmd) + case "check": + cmd_check(&cmd) + case "scan": + cmd_scan(&cmd) + case "sync": + cmd_sync(&cmd) + case "completion": + cmd_completion(&cmd) + case "uninstall": + cmd_uninstall(&cmd) + case: + fmt.wprintf(cmd.err, "Unknown command: %s\n", cmd.name) + write_usage(cmd.out) os.exit(1) } - spall_ctx = ctx - defer spall.context_destroy(&spall_ctx) - - spall_backing := make([]u8, spall.BUFFER_DEFAULT_SIZE) - defer delete(spall_backing) - - spall_buffer = spall.buffer_create(spall_backing, u32(sync.current_thread_id())) - defer spall.buffer_destroy(&spall_ctx, &spall_buffer) } - - when ODIN_DEBUG { - heap_track: mem.Tracking_Allocator - mem.tracking_allocator_init(&heap_track, context.allocator) - defer mem.tracking_allocator_destroy(&heap_track) - defer if len(heap_track.allocation_map) > 0 { - for _, leak in heap_track.allocation_map { - fmt.eprintf("LEAK: %v leaked %m\n", leak.location, leak.size) - } - } - context.allocator = mem.tracking_allocator(&heap_track) - - temp_track: mem.Tracking_Allocator - mem.tracking_allocator_init(&temp_track, context.temp_allocator) - defer mem.tracking_allocator_destroy(&temp_track) - context.temp_allocator = mem.tracking_allocator(&temp_track) - } - - defer free_all(context.temp_allocator) - - cmd, ok := parse_args(os.args, os.to_writer(os.stdout), os.to_writer(os.stderr)) - defer delete_command(&cmd) // delete flushes automatically - if !ok { - return - } - - switch cmd.name { - case "init": - cmd_init(&cmd) - case "version": - cmd_version(&cmd) - case "list": - cmd_list(&cmd) - case "backup", "add": - cmd_backup(&cmd) - case "remove": - cmd_remove(&cmd) - case "restore": - cmd_restore(&cmd) - case "edit-config": - cmd_edit_config(&cmd) - case "check": - cmd_check(&cmd) - case "scan": - cmd_scan(&cmd) - case "sync": - cmd_sync(&cmd) - case "completion": - cmd_completion(&cmd) - case "uninstall": - cmd_uninstall(&cmd) - case: - fmt.wprintf(cmd.err, "Unknown command: %s\n", cmd.name) - write_usage(cmd.out) - os.exit(1) - } -} +} // !GENDOCS when SPALL { @(instrumentation_enter)