diff options
Diffstat (limited to 'aoc2023/build/packages/snag/src')
-rw-r--r-- | aoc2023/build/packages/snag/src/snag.app.src | 8 | ||||
-rw-r--r-- | aoc2023/build/packages/snag/src/snag.erl | 74 | ||||
-rw-r--r-- | aoc2023/build/packages/snag/src/snag.gleam | 141 |
3 files changed, 0 insertions, 223 deletions
diff --git a/aoc2023/build/packages/snag/src/snag.app.src b/aoc2023/build/packages/snag/src/snag.app.src deleted file mode 100644 index 175e326..0000000 --- a/aoc2023/build/packages/snag/src/snag.app.src +++ /dev/null @@ -1,8 +0,0 @@ -{application, snag, [ - {vsn, "0.2.1"}, - {applications, [gleam_stdlib, - gleeunit]}, - {description, "A boilerplate-free ad-hoc error type"}, - {modules, [snag]}, - {registered, []} -]}. diff --git a/aoc2023/build/packages/snag/src/snag.erl b/aoc2023/build/packages/snag/src/snag.erl deleted file mode 100644 index a07f242..0000000 --- a/aoc2023/build/packages/snag/src/snag.erl +++ /dev/null @@ -1,74 +0,0 @@ --module(snag). --compile([no_auto_import, nowarn_unused_vars]). - --export([new/1, error/1, layer/2, context/2, pretty_print/1, line_print/1]). --export_type([snag/0]). - --type snag() :: {snag, binary(), list(binary())}. - --spec new(binary()) -> snag(). -new(Issue) -> - {snag, Issue, []}. - --spec error(binary()) -> {ok, any()} | {error, snag()}. -error(Issue) -> - {error, new(Issue)}. - --spec layer(snag(), binary()) -> snag(). -layer(Snag, Issue) -> - {snag, Issue, [erlang:element(2, Snag) | erlang:element(3, Snag)]}. - --spec context({ok, EXX} | {error, snag()}, binary()) -> {ok, EXX} | - {error, snag()}. -context(Result, Issue) -> - case Result of - {ok, _} -> - Result; - - {error, Snag} -> - {error, layer(Snag, Issue)} - end. - --spec pretty_print_cause(list(binary())) -> gleam@string_builder:string_builder(). -pretty_print_cause(Cause) -> - _pipe = Cause, - _pipe@1 = gleam@list:index_map( - _pipe, - fun(Index, Line) -> - gleam@string:concat( - [<<" "/utf8>>, - gleam@int:to_string(Index), - <<": "/utf8>>, - Line, - <<"\n"/utf8>>] - ) - end - ), - gleam@string_builder:from_strings(_pipe@1). - --spec pretty_print(snag()) -> binary(). -pretty_print(Snag) -> - Builder = gleam@string_builder:from_strings( - [<<"error: "/utf8>>, erlang:element(2, Snag), <<"\n"/utf8>>] - ), - gleam@string_builder:to_string(case erlang:element(3, Snag) of - [] -> - Builder; - - Cause -> - _pipe = Builder, - _pipe@1 = gleam@string_builder:append( - _pipe, - <<"\ncause:\n"/utf8>> - ), - gleam@string_builder:append_builder( - _pipe@1, - pretty_print_cause(Cause) - ) - end). - --spec line_print(snag()) -> binary(). -line_print(Snag) -> - _pipe = [gleam@string:append(<<"error: "/utf8>>, erlang:element(2, Snag)) | - erlang:element(3, Snag)], - gleam@string:join(_pipe, <<" <- "/utf8>>). diff --git a/aoc2023/build/packages/snag/src/snag.gleam b/aoc2023/build/packages/snag/src/snag.gleam deleted file mode 100644 index 8d39537..0000000 --- a/aoc2023/build/packages/snag/src/snag.gleam +++ /dev/null @@ -1,141 +0,0 @@ -import gleam -import gleam/string_builder -import gleam/string -import gleam/list -import gleam/int - -/// A Snag is a boilerplate-free error type that can be used to track why an -/// error happened, though does not store as much detail on specific errors as a -/// custom error type would. -/// -/// It is useful in code where it must either pass or fail, and when it fails we -/// want good debugging information to print to the user. i.e. Command line -/// tools, data processing pipelines, etc. -/// -/// If it not suited to code where the application needs to make a decision about -/// what to do in the event of an error, such as whether to give up or to try -/// again. i.e. Libraries, web application backends, API clients, etc. -/// In these situations it is recommended to create a custom type for your errors -/// as it can be pattern matched on and have any additional detail added as -/// fields. -pub type Snag { - Snag(issue: String, cause: List(String)) -} - -/// A concise alias for a `Result` that uses a `Snag` as the error value. -pub type Result(t) = - gleam.Result(t, Snag) - -/// Create a new `Snag` with the given issue text. -/// -/// See also the `error` function for creating a `Snag` wrapped in a `Result`. -/// -/// # Example -/// -/// ```gleam -/// > new("Not enough credit") -/// > |> line_print -/// "error: Not enough credit" -/// ``` -pub fn new(issue: String) -> Snag { - Snag(issue: issue, cause: []) -} - -/// Create a new `Snag` wrapped in a `Result` with the given issue text. -/// -/// # Example -/// -/// ```gleam -/// > error("Not enough credit") -/// Error(new("Not enough credit")) -/// ``` -pub fn error(issue: String) -> Result(success) { - Error(new(issue)) -} - -/// Add additional contextual information to a `Snag`. -/// -/// See also the `context` function for adding contextual information to a `Snag` -/// wrapped in a `Result`. -/// -/// # Example -/// -/// ```gleam -/// > new("Not enough credit") -/// > |> layer("Unable to make purchase") -/// > |> line_print -/// "error: Unable to make purchase <- Not enough credit" -/// ``` -pub fn layer(snag: Snag, issue: String) -> Snag { - Snag(issue: issue, cause: [snag.issue, ..snag.cause]) -} - -/// Add additional contextual information to a `Snag` wrapped in a `Result`. -/// -/// # Example -/// -/// ```gleam -/// > error("Not enough credit") -/// > |> context("Unable to make purchase") -/// > |> result.map_error(line_print) -/// Error("error: Unable to make purchase <- Not enough credit") -/// ``` -pub fn context(result: Result(success), issue: String) -> Result(success) { - case result { - Ok(_) -> result - Error(snag) -> Error(layer(snag, issue)) - } -} - -/// Turn a snag into a multi-line string, optimised for readability. -/// -/// # Example -/// -/// ```gleam -/// > new("Not enough credit") -/// > |> layer("Unable to make purchase") -/// > |> layer("Character creation failed") -/// > |> pretty_print -/// "error: Character creation failed -/// -/// cause: -/// 0: Unable to make purchase -/// 1: Not enough credit -/// " -/// ``` -pub fn pretty_print(snag: Snag) -> String { - let builder = string_builder.from_strings(["error: ", snag.issue, "\n"]) - - string_builder.to_string(case snag.cause { - [] -> builder - cause -> - builder - |> string_builder.append("\ncause:\n") - |> string_builder.append_builder(pretty_print_cause(cause)) - }) -} - -fn pretty_print_cause(cause) { - cause - |> list.index_map(fn(index, line) { - string.concat([" ", int.to_string(index), ": ", line, "\n"]) - }) - |> string_builder.from_strings -} - -/// Turn a snag into a single-line string, optimised for compactness. This may be -/// useful for logging snags. -/// -/// # Example -/// -/// ```gleam -/// > new("Not enough credit") -/// > |> layer("Unable to make purchase") -/// > |> layer("Character creation failed") -/// > |> pretty_print -/// "error: Character creation failed <- Unable to make purchase <- Not enough credit" -/// ``` -pub fn line_print(snag: Snag) -> String { - [string.append("error: ", snag.issue), ..snag.cause] - |> string.join(" <- ") -} |