Code Monkey home page Code Monkey logo

gap's Introduction

gap

Package Version Hex Docs

A Gleam library for comparing strings/lists and producing a textual (styled) representation of the differences.

A typical styled output from the comparison can look like this:

Image of two strings with highlighted differences

Installation

If available on Hex this package can be added to your Gleam project:

gleam add gap

Documentation can be found at https://hexdocs.pm/gap.

Usage

Introduction

Gap implements string/list comparison by finding the longest common subsequence. The result of the comparison are two sequences (one for each of the compared strings/lists) consisting of subsequences that are annotated as matching or non-matching.

For example comparing the strings in the example above will look as follows:

let comparison =
compare_strings(
    "lucy in the sky with diamonds",
    "lucy is  the shy with diagrams",
)
|> io.debug()
// StringComparison(
//   [
//     Match(["l", "u", "c", "y", " ", "i"]),
//     NoMatch(["n"]),
//     Match([" ", "t", "h", "e", " ", "s"]),
//     NoMatch(["k"]),
//     Match(["y", " ", "w", "i", "t", "h", " ", "d", "i", "a", "m"]),
//     NoMatch(["o", "n", "d"]),
//     Match(["s"]),
//   ],
//   [
//     Match(["l", "u", "c", "y", " ", "i"]),
//     NoMatch(["s", " "]),
//     Match([" ", "t", "h", "e", " ", "s"]),
//     NoMatch(["h"]),
//     Match(["y", " ", "w", "i", "t", "h", " ", "d", "i"]),
//     NoMatch(["a", "g", "r"]),
//     Match(["a", "m", "s"]),
//   ],
// )

Styling

This is useful information but a bit overwhelming to look at (specially for longer string) so the library has some built in functions to display the differences using colors instead.

Using the same example again we can style the result and print it to the console

let comparison =
compare_strings(
    "lucy in the sky with diamonds",
    "lucy is  the shy with diagrams",
)
|> to_styled()
io.println(comparison.first)
io.println(comparison.second)

This will give us something similar to the output above.

Comparing list

It is also possible to compare lists with elements of arbitrary types.

pub type Warning {
  Please
  Mind
  The(what: String)
}

compare_lists([Mind, The("Gap")], [Please, Mind, The("What")])
|> io.debug()
// ListComparison(
//   [Match([Mind]), NoMatch([The("Gap")])],
//   [NoMatch([Please]), Match([Mind]), NoMatch([The("What")])],
// )

Customize styling

The visual representation of the comparison can be customized. To do this use a Styling created from the comparison that should be styled. This example uses gleam_community/ansi to highlight the non-matches in different colors.

let comparison =
compare_strings(
    "Strings are made of smaller things",
    "Things are maybe smaller string",
)
|> from_comparison()
|> highlight(
    fn(first) { ansi.cyan(first) },
    fn(second) { ansi.magenta(second) },
    fn(matching) { matching },
)
|> to_styled_comparison()
io.println(comparison.first)
io.println(comparison.second)

This will output something similar to this

Image of two strings with highlighted differences

Serialization

Furthermore it is also possible to customize the styling by changing the way that the comparison is serialized. An easy way to do this is to use the utility function mk_generic_serializer which creates a serializer which some specific separator and a hook for surrounding the result with some content. Here is a somewhat contrived example

let comparison =
compare_lists(["one", "two", "three"], ["two", "two", "tree"])
|> from_comparison()
|> highlight(
    fn(first) { first <> " was not found in other" },
    fn(second) { second <> " was not found in other" },
)
|> serialize(mk_generic_serializer(
    ", and ",
    fn(result) { "Comparing the lists gave the following result: " <> result },
))
|> to_styled_comparison()
io.println(comparison.first)
io.println(comparison.second)
// Comparing the lists gave the following result: "one" was not found in other, and "two" was found in other, and "three" was not found in other
// Comparing the lists gave the following result: "two" was not found in other, and "two" was found in other, and "tree" was not found in other

Custom serialization

Serializers can of course have a custom implementation. The following example utilizes this together with custom highlighters, creating a patch-like output (this is not exactly the same as patch-format since that shows the changes in relation to the original - to do that both lists of matching/non-matching lines would need to be processed together)

let comparison =
compare_lists(
    [
    "pub type Gap = List(EmptyString)", "", "pub type Traveler {",
    "  OnTrain", "  OverGap(gap: Gap)", "  OnPlatform", "}",
    ],
    [
    "pub type Traveler {", "  OnTrain", "  OverGap(gap: String)",
    "  OnPlatform", "}",
    ],
)
|> from_comparison()
|> highlight(
    fn(first) { "+" <> first },
    fn(second) { "-" <> second },
    fn(matching) { " " <> matching },
)
|> serialize(fn(part) {
    case part {
    Part(acc, lines, highlight) ->
        acc <> {
        lines
        |> list.map(fn(line) { highlight(line) })
        |> string.join("\n")
        } <> "\n"
    All(result) -> result
    }
})
|> to_styled_comparison()
io.println(comparison.first)
io.println(comparison.second)
// +pub type Gap = List(EmptyString)
// +
//  pub type Traveler {
//    OnTrain
// +  OverGap(gap: Gap)
//    OnPlatform
//  }
// 
//  pub type Traveler {
//    OnTrain
// -  OverGap(gap: String)
//    OnPlatform
//  }

gap's People

Contributors

johnbjrk avatar

Stargazers

Masanori Ogino avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.