Skip to content

Import library#1

Merged
lupodevelop merged 12 commits into
mainfrom
import-library
Feb 8, 2026
Merged

Import library#1
lupodevelop merged 12 commits into
mainfrom
import-library

Conversation

@lupodevelop

Copy link
Copy Markdown
Owner

This pull request introduces the initial stable release of the humanize library for Gleam, providing helpers to make numbers, bytes, durations, lists, and time values human-friendly. The changes establish the public API, add documentation, set up CI, and include extensive tests for correctness and edge cases.

Release and Documentation

  • Added initial stable release candidate with public API functions for number, bytes, percent, duration, list, ordinal, and locale/time helpers, and documented them in CHANGELOG.md and README.md. [1] [2]
  • Added CONTRIBUTING.md with guidelines for contributing, reporting issues, and pull request requirements.
  • Updated LICENSE to clarify copyright ownership.

Project Setup

  • Added gleam.toml to define package metadata, dependencies, and repository links for publishing and documentation.
  • Added GitHub Actions workflow for CI, running tests and formatting checks on pushes and pull requests.

Testing and Locale Support

  • Added comprehensive unit tests for all API functions, edge cases, rounding, locale overrides, and property-based checks in test/humanize_test.gleam.
  • Added internal locale data for built-in languages and default fallback in src/internals/locales.gleam.

Create a .gitignore to exclude common Erlang/OTP artifacts: compiled .beam files, .ez release archives, the /build directory, and erl_crash.dump. This prevents build outputs and crash dumps from being committed to the repository.
Add gleam.toml for the new 'humanize' package with project metadata (name, version, description, license), repository and links, and dependency constraints. Includes gleam_stdlib (>=0.44.0 <2.0.0) and dev-dependency gleeunit (>=1.0.0 <2.0.0) to enable documentation generation and publishing to Hex.
Replace short copyright name with full name and alias in LICENSE. Changes "Copyright (c) 2026 Daniele" to "Copyright (c) 2026 - Scaratti Daniele ( aka: lupodevelop)" to clarify ownership attribution.
Add a generated Gleam manifest file declaring project dependencies and their version constraints. Includes gleam_stdlib (0.68.1) and gleeunit (1.9.0) with build tools, otp_app names, sources and requirement ranges. This file is generated by Gleam and typically does not require manual edits.
Add src/humanize.gleam providing a collection of human-friendly formatting helpers: compact number formatting (with decimals and decimal separator), bytes formatting (decimal and binary), percent formatting and ratios, duration (single-unit and precise multi-unit), list joining (with Oxford/ampersand options), ordinal suffixes, and time-ago formatting with locale data and runtime overrides. Introduces DecimalSeparator, NumberOpts, LocaleData types, various helper functions, and integrates with internals/locales for built-in locale lookups.
Introduce src/internals/locales.gleam providing internal localization data for relative time formatting. Adds locales_raw() with raw tuples for Italian, English, Spanish, French, German, and Portuguese (units and plural forms) and default_raw() as the English fallback; data is stored as raw tuples to avoid circular dependencies with the public LocaleData type.
Add a new Gleam test suite (test/humanize_test.gleam) exercising the humanize module. The file adds unit tests for number formatting (locales, options, boundaries, negatives), byte formatting (decimal/binary, large units, rounding/promotions, boundaries), durations and time-ago formatting (precision, future/past, locales and overrides), lists, percent formatting, ordinals, and misc edge cases. It also includes helper functions (pow10, pow_int, expected_find_denom, expected_bytes_decimal, find_next_unit) and property-style checks to validate monotonicity and rounding behavior, and is wired to gleeunit.
Replace the minimal README with a full project README: adds project logo and CI/packaging badges, a Quick API reference table, extensive usage examples (numbers, bytes, durations, lists, ordinals, time/i18n), locale override documentation and examples, percent examples, license info and development/run instructions. Improves documentation and developer onboarding by demonstrating common use cases and i18n customization.
Add new binary image file asset/img/humanize.png to the repository for use in the UI or documentation.
Add .github/workflows/test.yml to run CI for Gleam projects. The workflow triggers on push to master/main and on pull requests, checks out the repo, sets up OTP 28, Gleam 1.14.0 and rebar3 via erlef/setup-beam@v1, and runs `gleam deps download`, `gleam test`, and `gleam format --check`. The elixir-version setting is left commented.
Add initial project documentation: a CHANGELOG documenting the 1.0.0 release (public API list, built-in locales, tests, rounding promotion behavior, README updates, and a percent spacing fix) and a CONTRIBUTING guide outlining contribution workflow, testing/formatting commands (gleam format, gleam deps download && gleam test), PR guidelines, and licensing terms.
Add a section for OS-generated files and include .DS_Store so macOS metadata files are ignored. Also add a blank line for readability.
Copilot AI review requested due to automatic review settings February 8, 2026 16:01
@lupodevelop lupodevelop merged commit ac33cdf into main Feb 8, 2026
5 checks passed
@lupodevelop lupodevelop deleted the import-library branch February 8, 2026 16:01

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces an initial humanize Gleam library release that provides public APIs for human-friendly formatting of numbers, bytes, durations, lists, ordinals, and relative times with locale support, along with CI/docs/tests.

Changes:

  • Added core humanize module implementing formatting helpers and relative-time locale APIs.
  • Added built-in locale data and a comprehensive Gleam test suite.
  • Added project/release scaffolding (README/CHANGELOG/CONTRIBUTING, Gleam package config, CI workflow, license, gitignore, assets).

Reviewed changes

Copilot reviewed 9 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/humanize.gleam Implements the public API: number/bytes/percent/duration/list/ordinal/time formatting and locale override support.
src/internals/locales.gleam Adds built-in locale definitions and a default locale fallback.
test/humanize_test.gleam Adds extensive unit tests covering main APIs, edge cases, locale overrides, and boundary behavior.
.github/workflows/test.yml Adds CI to run formatting checks and tests on pushes/PRs.
gleam.toml Defines package metadata, dependencies, and publishing links.
manifest.toml Locks resolved Gleam dependencies for reproducible builds.
README.md Documents the library API and provides examples, including i18n usage.
CHANGELOG.md Documents the 1.0.0 release notes and behavior changes.
CONTRIBUTING.md Adds contribution guidelines and local dev/test instructions.
LICENSE Updates copyright attribution details.
.gitignore Adds standard Gleam/Erlang build artifact ignores.
asset/img/humanize.png Adds a project logo used in the README.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/humanize.gleam
case items {
[] -> ""
[a] -> a
[a, b] -> a <> conj <> b

Copilot AI Feb 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

list/1 and list_with_oxford/1 call list_locale(items, "", ...), but the [a, b] branch concatenates a <> conj <> b. When conj is empty this produces "ab" instead of the expected "a and b" (and will also break tests). Consider using the same default conjunction logic as the _ branch (e.g., treat empty conj as " and " for two items).

Suggested change
[a, b] -> a <> conj <> b
[a, b] -> {
let two_conj = case conj != "" {
True -> conj
False -> " and "
}
a <> two_conj <> b
}

Copilot uses AI. Check for mistakes.
Comment thread src/humanize.gleam
Comment on lines +315 to +317
True -> data.in_ <> " " <> core

False -> core <> " " <> data.ago

Copilot AI Feb 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relative time formatting assumes data.ago is always a suffix (core <> " " <> data.ago). Several built-in locales define ago as a prefix (e.g. French "il y a", German "vor", Spanish "hace"), so output will be grammatically incorrect and will not match the tests. Consider changing locale data to contain format templates (e.g. "{core} ago" / "il y a {core}") or add metadata to support prefix vs suffix placement.

Suggested change
True -> data.in_ <> " " <> core
False -> core <> " " <> data.ago
True -> {
// For future times, allow `data.in_` to be either a template
// containing "{core}" or a simple prefix.
case string.contains(data.in_, "{core}") {
True -> string.replace(data.in_, "{core}", core)
False -> data.in_ <> " " <> core
}
}
False -> {
// For past times, allow `data.ago` to be either a template
// containing "{core}" or a simple suffix.
case string.contains(data.ago, "{core}") {
True -> string.replace(data.ago, "{core}", core)
False -> core <> " " <> data.ago
}
}

Copilot uses AI. Check for mistakes.
Comment thread src/humanize.gleam
Comment on lines +26 to +44
fn pow10(n: Int) -> Int {
case n {
0 -> 1
_ -> 10 * pow10(n - 1)
}
}

/// Format an integer into a compact human-friendly string.
/// Example: `1234` -> "1.2K".
pub fn number(n: Int) -> String {
number_with(n, 1, Dot)
}

/// Format an integer using a specific number of decimals and decimal separator.
pub fn number_with(n: Int, decimals: Int, sep: DecimalSeparator) -> String {
let abs = case n < 0 {
True -> -n
False -> n
}

Copilot AI Feb 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pow10/1 does not handle negative inputs (it recurses forever), but decimals is a public Int parameter for number_with/3 (and is also used by percent helpers). Passing a negative decimals will crash at runtime. Consider validating/clamping decimals to >= 0 at the public API boundary (or change the API to accept a non-negative type/Result).

Copilot uses AI. Check for mistakes.
Comment thread src/humanize.gleam
LocaleData(_, _, _, _, u) -> u
}
let needed_units = case precise {
True -> max_units

Copilot AI Feb 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When precise is True, max_units is used directly as needed_units. If max_units <= 0, build_parts returns [] and the result becomes strings like "in " or " ago". Consider clamping max_units to at least 1 (or treating non-positive as 1) before calling build_parts.

Suggested change
True -> max_units
True -> {
// Clamp non-positive max_units to 1 to avoid empty parts like "in " or " ago"
case max_units <= 0 {
True -> 1
False -> max_units
}
}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants