Jane Street Core

repository·master·Indexed 23 days ago

https://github.com/janestreet/core

An industrial-strength, portable standard library for OCaml developed by Jane Street. Core serves as a feature-complete extension of the Base library, designed to work across different runtimes, including Javascript. It includes comprehensive tools for building command-line applications via the Command module, featuring applicative-style parameter specification, subcommand hierarchies, and advanced argument parsing.

Tokens
6.8K
Snippets
10
Records
48
Agent score
80%

What's inside janestreet-core

  1. Understanding the difference between Base and Core

    master

    Jane Street provides two distinct libraries that serve different purposes:

    • Base: A minimal, portable, and lightweight replacement for the OCaml standard library. It is designed to be highly stable.
    • Core: A more feature-rich extension of Base. It contains more code and dependencies, and its APIs evolve more quickly. Like Base, it is portable and works on Javascript.

    Many modules in Core are extensions of Base modules. For example, Core versions of modules might add bin_io support, use Stable to lock in APIs, or follow Core-specific conventions (such as Core.Map following Core conventions for comparator usage).

  2. How to use Core in your OCaml project

    master

    Core is an industrial-strength alternative to the OCaml standard library that is portable and works with Javascript. To use Core effectively, it is recommended to use the open! directive at the beginning of your file. This provides an overlay on the usual namespace, ensuring that Core's modules and definitions are prioritized over the standard library.

    open! Core
  3. Use Base_for_tests to generate tests for Base functors

    master
    The base_for_tests library provides specialized helpers designed to automate the generation of test suites for libraries that implement Base functors. It is particularly useful for testing functors such as Blit.Make or Binary_searchable.Make by providing standardized testing logic for these common interfaces.
  4. Handle command-line parsing outcomes

    master
    The Parsing_outcome module encapsulates the result of a parsing attempt. It tracks whether the parsing was successful (returning a Result.t) and whether the parser has consumed an argument (has_arg). This allows the command engine to distinguish between a successful parse that finished and one that is still waiting for input.
  5. Define command grammar with Anons.Grammar

    master

    The Anons.Grammar module allows you to define the structure of command arguments using a formal grammar. This is useful for generating usage strings like [arg ...] or [(arg) ...] automatically.

    Supported grammar types:

    • Zero: No arguments.
    • One of string: A single argument with a specific name.
    • Many of t: One or more occurrences of t (e.g., [arg ...]).
    • Maybe of t: Zero or one occurrence of t (e.g., [arg]).
    • Concat of t list: A sequence of arguments.
    • Ad_hoc of string: A raw usage string.

    You can use Anons.Grammar.usage to convert a grammar definition into a human-readable usage string.

  6. Define anonymous arguments with the Parser module

    master
    Anonymous arguments (positional arguments) are defined using the Parser module. You can define fixed-arity arguments (e.g., exactly one string) or variable-arity arguments (e.g., many or maybe). The parser uses an applicative interface (<*>, >>|) to compose argument requirements.
  7. Introspect command shapes with Command_shape

    master

    A Command_shape provides a machine-readable representation of a command's structure, including its subcommands, arguments, and documentation. This is useful for generating help text or programmatically inspecting a CLI's interface.

    A shape can be one of several types:

    • Basic: Contains Base_info (summary, readme, flags, and anonymous arguments).
    • Group: Contains Group_info (summary, readme, and a lazy list of subcommands).
    • Exec: Contains Exec_info (execution details) and a shape for the command being executed.
    • Lazy: A deferred shape.

    You can use fully_forced to convert a shape into a Fully_forced.t, which is a non-lazy, fully evaluated version suitable for comparison and serialization.

  8. Build a command-line application with Command.Param

    master

    The modern way to build command-line applications in this library is using Command.Param. This module uses an applicative-style interface, often combined with let%map_open from ppx_let, to compose command-line parameters (flags, anonymous arguments, etc.) into a single specification that is then passed to a command constructor like Command.basic.

    To use this pattern:

    1. Define your parameters using Command.Param.flag, Command.Param.anon, or other combinators.
    2. Use let%map_open to bind these parameters to local variables.
    3. Provide a function (the command body) that accepts these variables.
    4. Wrap the resulting specification in a command constructor like Command.basic and run it with Command.run.
    let () =
      let open Command.Let_syntax in
      Command.basic
        ~summary:"cook eggs"
        (let%map_open num_eggs =
           flag "num-eggs" (required int) ~doc:"COUNT cook this many eggs"
         and style =
           flag
             "style"
             (required (Arg_type.create Egg_style.of_string))
             ~doc:"OVER-EASY|SUNNY-SIDE-UP style of eggs"
         and recipient = anon ("recipient" %: string) in
         fun () ->
           (* Command body *)
           failwith "no eggs today")
      |> Command.run
  9. Use Stable Command_shape APIs

    master

    To ensure compatibility across different versions of the library, use the Command_shape.Stable module. This module provides versioned types that prevent breaking changes from affecting your code.

    • Stable.Base_info.V2: The current stable version for base command information.
    • Stable.Group_info.V2: The current stable version for command groups.
    • Stable.Exec_info.Model: The current stable version for execution information.
    • Stable.Fully_forced.V1: The current stable version for fully evaluated shapes.
  10. Create a command group with `Command.group`

    master

    Use Command.group to create a command that contains multiple subcommands. You provide a list of (name, command) pairs. The subcommands are evaluated lazily.

    Key options:

    • ~preserve_subcommand_order: If Some (), the order of subcommands in the input list is maintained. If None, they are sorted alphabetically.
    • ~body: An optional function that runs if no subcommand is provided.
  11. Analyze command argument grammar

    master

    The Anons.Grammar module defines the formal grammar of a command's anonymous arguments. This allows you to understand the expected pattern of arguments (e.g., whether they are required, optional, or repeated).

    Grammar.t constructors:

    • Zero: No arguments.
    • One of string: Exactly one argument of a specific type.
    • Many of t: Zero or more occurrences of a pattern.
    • Maybe of t: Zero or one occurrence of a pattern.
    • Concat of t list: A sequence of patterns.
    • Ad_hoc of string: An arbitrary pattern described by a string.

    Use Anons.Grammar.usage to convert a grammar definition into a human-readable usage string.

  12. Run a command specification with Command.Spec.parse

    master

    To execute the logic defined in a Command.Spec, use Command.Spec.parse. This function handles the command-line argument parsing, flag expansion, and environment updates. It returns the result of the parsing logic (the main function) which you can then execute.

    Note: This function will exit the process if parsing fails or if a help/version flag is triggered, unless handled via the on_failure callback.