Skip to content

Commit

Permalink
Hello, Joe!
Browse files Browse the repository at this point in the history
  • Loading branch information
lpil committed Dec 30, 2023
0 parents commit c6b813b
Show file tree
Hide file tree
Showing 7 changed files with 298 additions and 0 deletions.
23 changes: 23 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: test

on:
push:
branches:
- master
- main
pull_request:

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: erlef/setup-beam@v1
with:
otp-version: "26.0.2"
gleam-version: "0.33.0"
rebar3-version: "3"
# elixir-version: "1.15.4"
- run: gleam deps download
- run: gleam test
- run: gleam format --check src test
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.beam
*.ez
build
erl_crash.dump
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# justin

[![Package Version](https://img.shields.io/hexpm/v/justin)](https://hex.pm/packages/justin)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/justin/)

## Quick start

```sh
gleam run # Run the project
gleam test # Run the tests
gleam shell # Run an Erlang shell
```

## Installation

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

```sh
gleam add justin
```

and its documentation can be found at <https://hexdocs.pm/justin>.
16 changes: 16 additions & 0 deletions gleam.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name = "justin"
version = "1.0.0"

# Fill out these fields if you intend to generate HTML documentation or publish
# your project to the Hex package manager.
#
# description = ""
# licences = ["Apache-2.0"]
# repository = { type = "github", user = "username", repo = "project" }
# links = [{ title = "Website", href = "https://gleam.run" }]

[dependencies]
gleam_stdlib = "~> 0.32"

[dev-dependencies]
gleeunit = "~> 1.0"
11 changes: 11 additions & 0 deletions manifest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# This file was generated by Gleam
# You typically do not need to edit this file

packages = [
{ name = "gleam_stdlib", version = "0.34.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "1FB8454D2991E9B4C0C804544D8A9AD0F6184725E20D63C3155F0AEB4230B016" },
{ name = "gleeunit", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "D364C87AFEB26BDB4FB8A5ABDE67D635DC9FA52D6AB68416044C35B096C6882D" },
]

[requirements]
gleam_stdlib = { version = "~> 0.32" }
gleeunit = { version = "~> 1.0" }
101 changes: 101 additions & 0 deletions src/justin.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import gleam/string
import gleam/io
import gleam/list

// TODO: document
pub fn snake_case(text: String) -> String {
text
|> split_words
|> string.join("_")
|> string.lowercase
}

// TODO: document
pub fn camel_case(text: String) -> String {
text
|> split_words
|> list.index_map(fn(word, i) {
case i {
0 -> string.lowercase(word)
_ -> string.capitalise(word)
}
})
|> string.concat
}

// TODO: document
pub fn pascal_case(text: String) -> String {
text
|> split_words
|> list.map(string.capitalise)
|> string.concat
}

// TODO: document
pub fn kebab_case(text: String) -> String {
text
|> split_words
|> string.join("-")
|> string.lowercase
}

// TODO: document
pub fn sentence_case(text: String) -> String {
text
|> split_words
|> string.join(" ")
|> string.capitalise
}

fn split_words(text: String) -> List(String) {
text
|> string.to_graphemes
|> split(False, "", [])
}

fn split(
in: List(String),
up: Bool,
word: String,
words: List(String),
) -> List(String) {
case in {
[] if word == "" -> list.reverse(words)
[] -> list.reverse(add(words, word))

["\n", ..in]
| ["\t", ..in]
| ["!", ..in]
| ["?", ..in]
| ["#", ..in]
| [".", ..in]
| ["-", ..in]
| ["_", ..in]
| [" ", ..in] -> split(in, False, "", add(words, word))

[g, ..in] -> {
io.println(string.inspect(#(g, is_upper(g))))
case is_upper(g) {
// Lowercase, not a new word
False -> split(in, False, word <> g, words)

// Uppercase and inside an uppercase word, not a new word
True if up -> split(in, up, word <> g, words)

// Uppercase otherwise, a new word
True -> split(in, True, g, add(words, word))
}
}
}
}

fn add(words: List(String), word: String) -> List(String) {
case word {
"" -> words
_ -> [word, ..words]
}
}

fn is_upper(g: String) -> Bool {
string.lowercase(g) != g
}
121 changes: 121 additions & 0 deletions test/justin_test.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import gleeunit
import gleam/list
import justin

pub fn main() {
gleeunit.main()
}

const snake_cases = [
#("", ""),
#("snake case", "snake_case"),
#("snakeCase", "snake_case"),
#("Snake-Case", "snake_case"),
#("Snake_Case", "snake_case"),
#("SnakeCase", "snake_case"),
#("Snake.Case", "snake_case"),
#("SNAKE_CASE", "snake_case"),
#("--snake-case--", "snake_case"),
#("snake#case", "snake_case"),
#("snake?!case", "snake_case"),
#("snake\tcase", "snake_case"),
#("snake\ncase", "snake_case"),
#("λambdaΛambda", "λambda_λambda"),
]

const camel_cases = [
#("", ""),
#("snake case", "snakeCase"),
#("snakeCase", "snakeCase"),
#("Snake-Case", "snakeCase"),
#("Snake_Case", "snakeCase"),
#("SnakeCase", "snakeCase"),
#("Snake.Case", "snakeCase"),
#("SNAKE_CASE", "snakeCase"),
#("--snake-case--", "snakeCase"),
#("snake#case", "snakeCase"),
#("snake?!case", "snakeCase"),
#("snake\tcase", "snakeCase"),
#("snake\ncase", "snakeCase"),
#("λambda_λambda", "λambdaΛambda"),
]

const pascal_cases = [
#("", ""),
#("snake case", "SnakeCase"),
#("snakeCase", "SnakeCase"),
#("Snake-Case", "SnakeCase"),
#("Snake_Case", "SnakeCase"),
#("SnakeCase", "SnakeCase"),
#("Snake.Case", "SnakeCase"),
#("SNAKE_CASE", "SnakeCase"),
#("--snake-case--", "SnakeCase"),
#("snake#case", "SnakeCase"),
#("snake?!case", "SnakeCase"),
#("snake\tcase", "SnakeCase"),
#("snake\ncase", "SnakeCase"),
#("λambda_λambda", "ΛambdaΛambda"),
]

const kebab_cases = [
#("", ""),
#("snake case", "snake-case"),
#("snakeCase", "snake-case"),
#("Snake-Case", "snake-case"),
#("Snake_Case", "snake-case"),
#("SnakeCase", "snake-case"),
#("Snake.Case", "snake-case"),
#("SNAKE_CASE", "snake-case"),
#("--snake-case--", "snake-case"),
#("snake#case", "snake-case"),
#("snake?!case", "snake-case"),
#("snake\tcase", "snake-case"),
#("snake\ncase", "snake-case"),
#("λambda_λambda", "λambda-λambda"),
]

const sentence_cases = [
#("", ""),
#("snake case", "Snake case"),
#("snakeCase", "Snake case"),
#("Snake-Case", "Snake case"),
#("Snake_Case", "Snake case"),
#("SnakeCase", "Snake case"),
#("Snake.Case", "Snake case"),
#("SNAKE_CASE", "Snake case"),
#("--snake-case--", "Snake case"),
#("snake#case", "Snake case"),
#("snake?!case", "Snake case"),
#("snake\tcase", "Snake case"),
#("snake\ncase", "Snake case"),
#("λambda_λambda", "Λambda λambda"),
]

fn run_cases(cases: List(#(String, String)), function: fn(String) -> String) {
use #(in, out) <- list.each(cases)
let real = function(in)
case real == out {
True -> Nil
False -> panic as { in <> " should be " <> out <> ", got " <> real }
}
}

pub fn snake_test() {
run_cases(snake_cases, justin.snake_case)
}

pub fn camel_test() {
run_cases(camel_cases, justin.camel_case)
}

pub fn pascal_test() {
run_cases(pascal_cases, justin.pascal_case)
}

pub fn kebab_test() {
run_cases(kebab_cases, justin.kebab_case)
}

pub fn sentence_test() {
run_cases(sentence_cases, justin.sentence_case)
}

0 comments on commit c6b813b

Please sign in to comment.