-module(clip). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/clip.gleam"). -export([return/1, parameter/1, apply/2, command/1, command1/0, command2/0, command3/0, command4/0, fail/1, opt/2, arg/2, arg_many/2, arg_many1/2, flag/2, help/2, parse/2, subcommands_with_default/2, subcommands/1, run/2]). -export_type([command/1]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC(" Functions for building and running `Command`s.\n"). -opaque command(RAU) :: {command, clip@arg_info:arg_info(), gleam@option:option(clip@help:help()), fun((list(binary())) -> {ok, {RAU, list(binary())}} | {error, binary()})}. -file("src/clip.gleam", 32). ?DOC( " The `return` function takes a value `val` and produces a `Command` that, when\n" " run, produces `val`. You should only call this function directly when your\n" " command doesn't require any arguments. Otherwise, use `clip.command`.\n" "\n" " ```gleam\n" " clip.return(1) |> clip.run([\"whatever\"])\n" "\n" " // Ok(1)\n" " ```\n" "\n" " See the [subcommand example](https://github.com/drewolson/clip/tree/main/examples/subcommand)\n" " for idiomatic usage of `return`.\n" ). -spec return(RAV) -> command(RAV). return(Val) -> {command, clip@arg_info:empty(), none, fun(Args) -> {ok, {Val, Args}} end}. -file("src/clip.gleam", 57). ?DOC( " The `parameter` function provides an alternative syntax for building curried\n" " functions. The following two code blocks are equivalent:\n" "\n" " ```gleam\n" " fn(a) {\n" " fn(b) {\n" " thing(a, b)\n" " }\n" " }\n" " ```\n" "\n" " ```gleam\n" " {\n" " use a <- clip.parameter\n" " use b <- clip.parameter\n" "\n" " thing(a, b)\n" " }\n" " ```\n" "\n" " You can use either style when calling `clip.command`.\n" ). -spec parameter(fun((RAX) -> RAY)) -> fun((RAX) -> RAY). parameter(F) -> F. -file("src/clip.gleam", 63). ?DOC( " Don't call this function directly. Rather, call `cli.opt`, `clip.flag`,\n" " `clip.arg`, `clip.arg_many`, or `clip.arg_many1`.\n" ). -spec apply(command(fun((RAZ) -> RBA)), command(RAZ)) -> command(RBA). apply(Mf, Ma) -> {command, clip@arg_info:merge(erlang:element(2, Mf), erlang:element(2, Ma)), gleam@option:'or'(erlang:element(3, Mf), erlang:element(3, Ma)), fun(Args) -> gleam@result:'try'( (erlang:element(4, Mf))(Args), fun(_use0) -> {F, Args1} = _use0, gleam@result:'try'( (erlang:element(4, Ma))(Args1), fun(_use0@1) -> {A, Args2} = _use0@1, {ok, {F(A), Args2}} end ) end ) end}. -file("src/clip.gleam", 91). ?DOC( " The `command` function is use to start building a parser. You provide a\n" " curried function and then provide arguments to be supplied to that function.\n" "\n" " ```gleam\n" " clip.command({\n" " use a <- clip.parameter\n" " use b <- clip.parameter\n" "\n" " #(a, b)\n" " })\n" " |> clip.opt(opt.new(\"first\"))\n" " |> clip.opt(opt.new(\"second\"))\n" " |> clip.run([\"--first\", \"foo\", \"--second\", \"bar\"])\n" "\n" " // Ok(#(\"foo\", \"bar\"))\n" " ```\n" ). -spec command(fun((RBE) -> RBF)) -> command(fun((RBE) -> RBF)). command(F) -> return(F). -file("src/clip.gleam", 104). ?DOC( " A pre-built command that takes a single argument and returns its value.\n" "\n" " ```gleam\n" " clip.command1()\n" " |> clip.opt(opt.new(\"first\"))\n" " |> clip.run([\"--first\", \"foo\"])\n" "\n" " // Ok(\"foo\")\n" " ```\n" ). -spec command1() -> command(fun((RBH) -> RBH)). command1() -> return(fun(A) -> A end). -file("src/clip.gleam", 119). ?DOC( " A pre-built command that takes two arguments and returns a tuple of their\n" " values.\n" "\n" " ```gleam\n" " clip.command2()\n" " |> clip.opt(opt.new(\"first\"))\n" " |> clip.opt(opt.new(\"second\"))\n" " |> clip.run([\"--first\", \"foo\", \"--second\", \"bar\"])\n" "\n" " // Ok(#(\"foo\", \"bar\"))\n" " ```\n" ). -spec command2() -> command(fun((RBJ) -> fun((RBK) -> {RBJ, RBK}))). command2() -> return(fun(A) -> fun(B) -> {A, B} end end). -file("src/clip.gleam", 135). ?DOC( " A pre-built command that takes three arguments and returns a tuple of their\n" " values.\n" "\n" " ```gleam\n" " clip.command3()\n" " |> clip.opt(opt.new(\"first\"))\n" " |> clip.opt(opt.new(\"second\"))\n" " |> clip.opt(opt.new(\"third\"))\n" " |> clip.run([\"--first\", \"foo\", \"--second\", \"bar\", \"--third\", \"baz\"])\n" "\n" " // Ok(#(\"foo\", \"bar\", \"baz\"))\n" " ```\n" ). -spec command3() -> command(fun((RBM) -> fun((RBN) -> fun((RBO) -> {RBM, RBN, RBO})))). command3() -> return(fun(A) -> fun(B) -> fun(C) -> {A, B, C} end end end). -file("src/clip.gleam", 152). ?DOC( " A pre-built command that takes four arguments and returns a tuple of their\n" " values.\n" "\n" " ```gleam\n" " clip.command4()\n" " |> clip.opt(opt.new(\"first\"))\n" " |> clip.opt(opt.new(\"second\"))\n" " |> clip.opt(opt.new(\"third\"))\n" " |> clip.opt(opt.new(\"fourth\"))\n" " |> clip.run([\"--first\", \"foo\", \"--second\", \"bar\", \"--third\", \"baz\", \"--fourth\", \"qux\"])\n" "\n" " // Ok(#(\"foo\", \"bar\", \"baz\", \"qux\"))\n" " ```\n" ). -spec command4() -> command(fun((RBQ) -> fun((RBR) -> fun((RBS) -> fun((RBT) -> {RBQ, RBR, RBS, RBT}))))). command4() -> return(fun(A) -> fun(B) -> fun(C) -> fun(D) -> {A, B, C, D} end end end end). -file("src/clip.gleam", 157). ?DOC(" Creates a `Command` that always produces `Error(message)` when run.\n"). -spec fail(binary()) -> command(any()). fail(Message) -> {command, clip@arg_info:empty(), none, fun(_) -> {error, Message} end}. -file("src/clip.gleam", 171). ?DOC( " Parse an option built using the `clip/opt` module and provide it to a\n" " `Command` function build using `clip.command()`\n" "\n" " ```gleam\n" " clip.command(fn(a) { a })\n" " |> clip.opt(opt.new(\"first\"))\n" " |> clip.run([\"--first\", \"foo\"])\n" "\n" " // Ok(\"foo\")\n" " ```\n" ). -spec opt(command(fun((RBX) -> RBY)), clip@opt:opt(RBX)) -> command(RBY). opt(Command, Opt) -> apply( Command, {command, clip@opt:to_arg_info(Opt), none, fun(_capture) -> clip@opt:run(Opt, _capture) end} ). -file("src/clip.gleam", 192). ?DOC( " Parse the next positional argument built using the `clip/arg` module and\n" " provide it to a `Command` function build using `clip.command()`\n" "\n" " ```gleam\n" " clip.command(fn(a) { a })\n" " |> clip.arg(arg.new(\"foo\"))\n" " |> clip.run([\"foo\"])\n" "\n" " // Ok(\"foo\")\n" " ```\n" "\n" " `arg` will not attempt to parse options starting with `-` unless the\n" " special `--` value has been previously passed or the option is a negative\n" " integer or float.\n" ). -spec arg(command(fun((RCC) -> RCD)), clip@arg:arg(RCC)) -> command(RCD). arg(Command, Arg) -> apply( Command, {command, clip@arg:to_arg_info(Arg), none, fun(_capture) -> clip@arg:run(Arg, _capture) end} ). -file("src/clip.gleam", 216). ?DOC( " Parse the next zero or more positional arguments built using the `clip/arg`\n" " module and provide them as a `List` to a `Command` function build using\n" " `clip.command()`. `arg_many` is greedy, parsing as many options as possible\n" " until parsing fails. If zero values are parsed successfuly, an empty\n" " `List` is provided.\n" "\n" " ```gleam\n" " clip.command(fn(a) { a })\n" " |> clip.arg_many(arg.new(\"foo\"))\n" " |> clip.run([\"foo\", \"bar\", \"baz\"])\n" "\n" " // Ok([\"foo\", \"bar\", \"baz\"])\n" " ```\n" "\n" " `arg_many` will not attempt to parse options starting with `-` unless the\n" " special `--` value has been previously passed or the option is a negative\n" " integer or float.\n" ). -spec arg_many(command(fun((list(RCH)) -> RCJ)), clip@arg:arg(RCH)) -> command(RCJ). arg_many(Command, Arg) -> apply( Command, {command, clip@arg:to_arg_info_many(Arg), none, fun(_capture) -> clip@arg:run_many(Arg, _capture) end} ). -file("src/clip.gleam", 239). ?DOC( " Parse the next one or more positional arguments built using the `clip/arg`\n" " module and provide them as a `List` to a `Command` function build using\n" " `clip.command()`. `arg_many` is greedy, parsing as many options as possible\n" " until parsing fails. Parsing fails if zero values are parsed successfully.\n" "\n" " ```gleam\n" " clip.command(fn(a) { a })\n" " |> clip.arg_many1(arg.new(\"foo\"))\n" " |> clip.run([\"foo\", \"bar\", \"baz\"])\n" "\n" " // Ok([\"foo\", \"bar\", \"baz\"])\n" " ```\n" "\n" " `arg_many1` will not attempt to parse options starting with `-` unless the\n" " special `--` value has been previously passed or the option is a negative\n" " integer or float.\n" ). -spec arg_many1(command(fun((list(RCN)) -> RCP)), clip@arg:arg(RCN)) -> command(RCP). arg_many1(Command, Arg) -> apply( Command, {command, clip@arg:to_arg_info_many1(Arg), none, fun(_capture) -> clip@arg:run_many1(Arg, _capture) end} ). -file("src/clip.gleam", 259). ?DOC( " Parse a flag built using the `clip/flag` module and provide it to a\n" " `Command` function build using `clip.command()`\n" "\n" " ```gleam\n" " clip.command(fn(a) { a })\n" " |> clip.flag(flag.new(\"foo\"))\n" " |> clip.run([\"--foo\"])\n" "\n" " // Ok(True)\n" " ```\n" ). -spec flag(command(fun((boolean()) -> RCT)), clip@flag:flag()) -> command(RCT). flag(Command, Flag) -> apply( Command, {command, clip@flag:to_arg_info(Flag), none, fun(_capture) -> clip@flag:run(Flag, _capture) end} ). -file("src/clip.gleam", 307). ?DOC( " Add the help (`-h`, `--help`) flags to your program to display usage help\n" " to the user. See the `clip/help` module for producing simple and custom help\n" " text.\n" ). -spec help(command(RDN), clip@help:help()) -> command(RDN). help(Command, Help) -> {command, erlang:element(2, Command), {some, Help}, erlang:element(4, Command)}. -file("src/clip.gleam", 311). -spec wrap_help(command(RDQ), clip@help:help()) -> fun((list(binary())) -> {ok, {RDQ, list(binary())}} | {error, binary()}). wrap_help(Command, Help) -> Help_info = begin _record = clip@arg_info:empty(), {arg_info, erlang:element(2, _record), erlang:element(3, _record), [{flag_info, <<"help"/utf8>>, {some, <<"h"/utf8>>}, {some, <<"Print this help"/utf8>>}}], erlang:element(5, _record)} end, fun(Args) -> case Args of [<<"-h"/utf8>> | _] -> {error, clip@help:run( Help, clip@arg_info:merge( erlang:element(2, Command), Help_info ) )}; [<<"--help"/utf8>> | _] -> {error, clip@help:run( Help, clip@arg_info:merge( erlang:element(2, Command), Help_info ) )}; Other -> (erlang:element(4, Command))(Other) end end. -file("src/clip.gleam", 336). ?DOC( " Use a `Command(a)` to parse a list of command line options. If parsing is\n" " successful, an `Ok(#(a, List(String)))` is returned containing the parsed\n" " value and any left over options. If parsing fails, an `Error(String)` is\n" " returned. The `Error` value is intended to be printed to the user.\n" "\n" " You should use the `clip.run` function instead of `clip.parse`, unless you\n" " need to deal with left over options after successful parsing.\n" ). -spec parse(command(RDW), list(binary())) -> {ok, {RDW, list(binary())}} | {error, binary()}. parse(Command, Args) -> F = case erlang:element(3, Command) of none -> erlang:element(4, Command); {some, Help} -> wrap_help(Command, Help) end, F(Args). -file("src/clip.gleam", 266). -spec run_subcommands( list({binary(), command(RCW)}), command(RCW), list(binary()) ) -> {ok, {RCW, list(binary())}} | {error, binary()}. run_subcommands(Subcommands, Default, Args) -> case {Subcommands, Args} of {[{Name, Command} | _], [Head | Rest]} when Name =:= Head -> parse(Command, Rest); {[_ | Rest@1], _} -> run_subcommands(Rest@1, Default, Args); {[], _} -> parse(Default, Args) end. -file("src/clip.gleam", 282). ?DOC( " Build a command with subcommands and a default top-level command if no\n" " subcommand matches. This is an advanced use case, see the examples directory\n" " for more help.\n" ). -spec subcommands_with_default(list({binary(), command(RDE)}), command(RDE)) -> command(RDE). subcommands_with_default(Subcommands, Default) -> Sub_names = gleam@list:map(Subcommands, fun(P) -> erlang:element(1, P) end), Sub_arg_info = begin _record = erlang:element(2, Default), {arg_info, erlang:element(2, _record), erlang:element(3, _record), erlang:element(4, _record), Sub_names} end, apply( return(fun(A) -> A end), {command, Sub_arg_info, none, fun(_capture) -> run_subcommands(Subcommands, Default, _capture) end} ). -file("src/clip.gleam", 300). ?DOC( " Build a command with subcommands. This is an advanced use case, see the\n" " examples directory for more help.\n" ). -spec subcommands(list({binary(), command(RDJ)})) -> command(RDJ). subcommands(Subcommands) -> subcommands_with_default( Subcommands, fail(<<"No subcommand provided"/utf8>>) ). -file("src/clip.gleam", 351). ?DOC( " Run a command with a list of command line options. Running a `Command(a)`\n" " will return either `Ok(a)` or an `Error(String)`. The `Error` value is\n" " intended to be printed to the user.\n" ). -spec run(command(REC), list(binary())) -> {ok, REC} | {error, binary()}. run(Command, Args) -> case parse(Command, Args) of {ok, {A, _}} -> {ok, A}; {error, E} -> {error, E} end.