Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new function-based ansi colouring for helptext headers #54

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## [Unreleased](https://github.com/TanklesXL/glint/compare/v1.0.1...HEAD)

- use punning internally, requires gleam >= 1.4
- new function-based helptext header style API
- deprecate old gleam_community/colour based pretty help API

# v1

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ pub fn main() {
// with an app name of "hello", this is used when printing help text
|> glint.with_name("hello")
// with pretty help enabled, using the built-in colours
|> glint.pretty_help(glint.default_pretty_help())
|> glint.with_default_header_style
// with a root command that executes the `hello` function
|> glint.add(at: [], do: hello())
// execute given arguments from stdin
Expand Down
2 changes: 1 addition & 1 deletion gleam.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name = "glint"
version = "1.0.1"
version = "1.1.0-dev"

# Fill out these fields if you intend to generate HTML documentation or publishname = "glint"
# your project to the Hex package manager.
Expand Down
5 changes: 3 additions & 2 deletions manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@

packages = [
{ name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" },
{ name = "birdie", version = "1.1.8", build_tools = ["gleam"], requirements = ["argv", "filepath", "glance", "gleam_community_ansi", "gleam_erlang", "gleam_stdlib", "justin", "rank", "simplifile", "trie_again"], otp_app = "birdie", source = "hex", outer_checksum = "D225C0A3035FCD73A88402925A903AAD3567A1515C9EAE8364F11C17AD1805BB" },
{ name = "birdie", version = "1.2.0", build_tools = ["gleam"], requirements = ["argv", "edit_distance", "filepath", "glance", "gleam_community_ansi", "gleam_erlang", "gleam_stdlib", "justin", "rank", "simplifile", "trie_again"], otp_app = "birdie", source = "hex", outer_checksum = "7EE6286C5660650143A5AC69E1D900DA1B6EAF3C6EBB7E50AC3DBF06511279CC" },
{ name = "edit_distance", version = "2.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "edit_distance", source = "hex", outer_checksum = "A1E485C69A70210223E46E63985FA1008B8B2DDA9848B7897469171B29020C05" },
{ name = "filepath", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "EFB6FF65C98B2A16378ABC3EE2B14124168C0CE5201553DE652E2644DCFDB594" },
{ name = "glance", version = "0.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "glexer"], otp_app = "glance", source = "hex", outer_checksum = "8F3314D27773B7C3B9FB58D8C02C634290422CE531988C0394FA0DF8676B964D" },
{ name = "gleam_community_ansi", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "FE79E08BF97009729259B6357EC058315B6FBB916FAD1C2FF9355115FEB0D3A4" },
{ name = "gleam_community_ansi", version = "1.4.1", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "4CD513FC62523053E62ED7BAC2F36136EC17D6A8942728250A9A00A15E340E4B" },
{ name = "gleam_community_colour", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "795964217EBEDB3DA656F5EB8F67D7AD22872EB95182042D3E7AFEF32D3FD2FE" },
{ name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" },
{ name = "gleam_json", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "9063D14D25406326C0255BDA0021541E797D8A7A12573D849462CAFED459F6EB" },
Expand Down
107 changes: 100 additions & 7 deletions src/glint.gleam
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import gleam
import gleam/dict
import gleam/float
import gleam/function
import gleam/int
import gleam/io
import gleam/list
import gleam/option.{type Option, None, Some}
import gleam/result
import gleam/string
import gleam_community/ansi
import gleam_community/colour.{type Colour}
import glint/constraint
import glint/internal/help
Expand All @@ -20,7 +22,7 @@ import snag.{type Snag}
///
type Config {
Config(
pretty_help: Option(PrettyHelp),
pretty_help: HeaderFormat,
name: Option(String),
as_module: Bool,
description: Option(String),
Expand All @@ -32,8 +34,79 @@ type Config {
)
}

type HeaderFormat {
HeaderFormat(
usage: fn(String) -> String,
flags: fn(String) -> String,
subcommands: fn(String) -> String,
)
}

/// Set the style for each of the glint helptext headers (usage, flags, subcommands).
///
/// This function will likely be used with colouring functions from [gleam_community/ansi](https://hexdocs.pm/gleam_community_ansi/).
///
/// When setting your own header styles, you may want to leverage the default formatting as provided by [`glint.default_header_format`](#default_header_format)
/// which can be composed witth other functions from [gleam_community/ansi](https://hexdocs.pm/gleam_community_ansi/)..
///
///
/// Example:
///
/// ```gleam
/// glint.with_header_style(
/// glint,
/// usage: fn(s) { s |> glint.default_header_format |> ansi.cyan },
/// flags: fn(s) { s |> glint.default_header_format |> ansi.magenta },
/// subcommands: fn(s) { s |> glint.default_header_format |> ansi.yellow },
/// )
/// ```
pub fn with_header_style(
glint: Glint(a),
usage usage: fn(String) -> String,
flags flags: fn(String) -> String,
subcommands subcommands: fn(String) -> String,
) -> Glint(a) {
Glint(
..glint,
config: Config(
..glint.config,
pretty_help: HeaderFormat(usage:, flags:, subcommands:),
),
)
}

/// This function sets the glint help text header styles using glint's defaults.
///
/// Each help text header is formatted as bold, italic and underline (see [`glint.default_header_format`](#default_header_format)).
///
/// The default colours are ANSI compatible as follows:
/// - usage: cyan
/// - flags: pink
/// - subcommands: yellow
///
pub fn with_default_header_style(glint: Glint(a)) -> Glint(a) {
with_header_style(
glint,
usage: fn(s) { s |> default_header_format |> ansi.cyan },
flags: fn(s) { s |> default_header_format |> ansi.pink },
subcommands: fn(s) { s |> default_header_format |> ansi.yellow },
)
}

/// Style heading text as bold, underlined and italic.
///
/// This function can be combined with other functions from [gleam_community/ansi](https://hexdocs.pm/gleam_community_ansi/)
///
pub fn default_header_format(heading: String) -> String {
heading
|> ansi.bold
|> ansi.underline
|> ansi.italic
}

/// PrettyHelp defines the header colours to be used when styling help text
///
@deprecated("this type will be removed in an upcoming version of glint")
pub type PrettyHelp {
PrettyHelp(usage: Colour, flags: Colour, subcommands: Colour)
}
Expand All @@ -43,7 +116,11 @@ pub type PrettyHelp {
/// default config
///
const default_config = Config(
pretty_help: None,
pretty_help: HeaderFormat(
function.identity,
function.identity,
function.identity,
),
name: None,
as_module: False,
description: None,
Expand All @@ -58,10 +135,25 @@ const default_config = Config(

/// Enable custom colours for help text headers.
///
/// For a pre-made style, pass in [`glint.default_pretty_help`](#default_pretty_help)
/// For a pre-made style, pass in [`glint.with_default_header_style`](#with_default_header_style) instead.
///
@deprecated("use glint.with_header_style instead")
pub fn pretty_help(glint: Glint(a), pretty: PrettyHelp) -> Glint(a) {
Glint(..glint, config: Config(..glint.config, pretty_help: Some(pretty)))
let style = fn(s: String, colour: colour.Colour) -> String {
s |> default_header_format |> ansi.colour(colour)
}

Glint(
..glint,
config: Config(
..glint.config,
pretty_help: HeaderFormat(
usage: style(_, pretty.usage),
flags: style(_, pretty.flags),
subcommands: style(_, pretty.subcommands),
),
),
)
}

/// Give the current glint application a name.
Expand Down Expand Up @@ -623,6 +715,7 @@ pub fn run_and_handle(
///
/// buttercup (r: 252, g: 226, b: 174) colour for subcommands
///
@deprecated("use glint.with_default_header_style instead")
pub fn default_pretty_help() -> PrettyHelp {
let assert Ok(usage_colour) = colour.from_rgb255(182, 255, 234)
let assert Ok(flags_colour) = colour.from_rgb255(255, 175, 243)
Expand Down Expand Up @@ -652,9 +745,9 @@ fn cmd_help(path: List(String), cmd: CommandNode(a), config: Config) -> String {
fn build_help_config(config: Config) -> help.Config {
help.Config(
name: config.name,
usage_colour: option.map(config.pretty_help, fn(p) { p.usage }),
flags_colour: option.map(config.pretty_help, fn(p) { p.flags }),
subcommands_colour: option.map(config.pretty_help, fn(p) { p.subcommands }),
usage_colour: config.pretty_help.usage,
flags_colour: config.pretty_help.flags,
subcommands_colour: config.pretty_help.subcommands,
as_module: config.as_module,
description: config.description,
indent_width: config.indent_width,
Expand Down
34 changes: 6 additions & 28 deletions src/glint/internal/help.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,8 @@ import gleam/int
import gleam/list
import gleam/option.{type Option, None, Some}
import gleam/string
import gleam_community/ansi
import gleam_community/colour.{type Colour}
import glint/internal/utils

/// Style heading text with the provided rgb colouring
/// this is only intended for use within glint itself.
///
fn heading_style(heading: String, colour: Colour) -> String {
heading
|> ansi.bold
|> ansi.underline
|> ansi.italic
|> ansi.hex(colour.to_rgb_hex(colour))
}

// --- HELP: CONSTANTS ---
//
pub const help_flag = Flag(Metadata("help", "Print help information"), "")
Expand All @@ -38,9 +25,9 @@ pub type ArgsCount {
pub type Config {
Config(
name: Option(String),
usage_colour: Option(Colour),
flags_colour: Option(Colour),
subcommands_colour: Option(Colour),
usage_colour: fn(String) -> String,
flags_colour: fn(String) -> String,
subcommands_colour: fn(String) -> String,
as_module: Bool,
description: Option(String),
indent_width: Int,
Expand Down Expand Up @@ -175,10 +162,7 @@ fn command_help_to_usage_string(help: Command, config: Config) -> String {
|> utils.wordwrap(max_usage_width)
|> string.join("\n" <> string.repeat(" ", config.indent_width * 2))

case config.usage_colour {
None -> usage_heading
Some(pretty) -> heading_style(usage_heading, pretty)
}
config.usage_colour(usage_heading)
<> "\n"
<> string.repeat(" ", config.indent_width)
<> content
Expand All @@ -197,10 +181,7 @@ fn flags_help_to_string(help: List(Flag), config: Config) -> String {
|> utils.max_string_length
|> int.max(config.min_first_column_width)

let heading = case config.flags_colour {
None -> flags_heading
Some(pretty) -> heading_style(flags_heading, pretty)
}
let heading = config.flags_colour(flags_heading)

let content =
to_spaced_indented_string(
Expand Down Expand Up @@ -237,10 +218,7 @@ fn subcommands_help_to_string(help: List(Metadata), config: Config) -> String {
|> utils.max_string_length
|> int.max(config.min_first_column_width)

let heading = case config.subcommands_colour {
None -> subcommands_heading
Some(pretty) -> heading_style(subcommands_heading, pretty)
}
let heading = config.subcommands_colour(subcommands_heading)

let content =
to_spaced_indented_string(
Expand Down
2 changes: 1 addition & 1 deletion test/examples/hello.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ pub fn app() {
// show in usage text that the current app is run as a gleam module
|> glint.as_module
// with pretty help enabled, using the built-in colours
|> glint.pretty_help(glint.default_pretty_help())
|> glint.with_default_header_style
// with group level flags
// with flag `caps` for all commands (equivalent of using glint.global_flag)
|> glint.group_flag([], caps_flag())
Expand Down
1 change: 1 addition & 0 deletions test/glint_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ pub fn global_and_group_flags_test() {
|> glint.execute(["sub", "sub", "--sub_group_flag=2"])
}

@deprecated("remove when the pretty help removal happens")
pub fn default_pretty_help_test() {
// default_pretty_help has asserts
// we need to call the function to make sure it does not crash
Expand Down