Skip to content

Commit

Permalink
Merge pull request #208 from appthrust/feat-add-outdent-module
Browse files Browse the repository at this point in the history
feat: add `outdent` module
  • Loading branch information
Peefy authored Aug 9, 2024
2 parents 489a254 + 13d65f3 commit 9efb46c
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 0 deletions.
66 changes: 66 additions & 0 deletions outdent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# KCL outdent Module

The `outdent` module provides a function to remove common leading whitespace from multi-line strings in KCL. This functionality is similar to:

- Python's `textwrap.dedent()`
- Kotlin's `trimMargin()`
- Scala's `stripMargin`
- The `outdent` NPM package for JavaScript
- Rust's `indoc` crate

## Features

- Removes common leading whitespace from multi-line strings
- Preserves relative indentation within the text
- Handles both spaces and tabs
- Trims leading and trailing blank lines

## Usage

Here's a basic example of how to use the `outdent` function:

main.k:

```kcl
import outdent
input = """
This is an example
of a multi-line string
with varying indentation
"""
output = outdent.outdent(input)
```

Run the script with:

```shell
kcl run main.k --format yaml
```

Output:

```yaml
input: "\n This is an example\n of a multi-line string\n with varying indentation\n "
output: |-
This is an example
of a multi-line string
with varying indentation
```
## Function Signature
```rust
outdent(text: str) -> str
```
- `text`: The input string to be outdented
- Returns: A new string with common leading whitespace removed

## Testing

The module includes a comprehensive test suite in `main_test.k`. To run the tests, use the KCL test runner:

```shell
kcl test
```
4 changes: 4 additions & 0 deletions outdent/kcl.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[package]
name = "outdent"
version = "0.1.0"
description = "`outdent` is ...(write here)"
Empty file added outdent/kcl.mod.lock
Empty file.
22 changes: 22 additions & 0 deletions outdent/main.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import regex

outdent = lambda text: str {
# Split the text into lines, preserving line endings
lines = regex.split(text, "\r\n|\n")
# Function to get leading whitespace
get_leading_whitespace = lambda line: str {
whitespace = regex.findall(line, "^\s+")
whitespace[0] if whitespace else ""
}
# Find non-empty lines and their indentations
non_empty_lines = [line for line in lines if line.strip()]
indents = [get_leading_whitespace(line) for line in non_empty_lines]
indentations = [len(get_leading_whitespace(line)) for line in non_empty_lines]
# Find the minimum indentation
min_indent = min([""] | indentations)
# Remove the common indent and join the lines
outdented_lines = [line[min_indent::] if line.strip() else line for line in lines]
result = "\n".join(outdented_lines)
# Trim leading and trailing blank lines
regex.replace(result, r'^\s*\n|\n\s*$', '')
}
68 changes: 68 additions & 0 deletions outdent/main_test.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
test_outdent_basic = lambda {
input = """
line1
line2
line3
line4
"""
expected = """
line1
line2
line3
line4
"""
assert outdent(input) == expected.strip(), "Basic indentation test failed"
}
test_outdent_empty_lines = lambda {
input = """

line1
line2
line3

"""
expected = """
line1
line2
line3
"""
assert outdent(input) == expected.strip(), "Empty lines test failed"
}
test_outdent_no_common_indent = lambda {
input = """
line1
line2
line3
"""
expected = """ line1
line2
line3"""
assert outdent(input) == expected, "No common indent test failed"
}
test_outdent_empty_string = lambda {
assert outdent("") == "", "Empty string test failed"
}
test_outdent_single_line = lambda {
assert outdent(" single line") == "single line", "Single line test failed"
}
test_outdent_tabs = lambda {
input = """
\tline1
\t\tline2
\t\t\tline3
"""
expected = """
line1
\tline2
\t\tline3
"""
assert outdent(input) == expected.strip(), "Tabs test failed"
}
test_outdent_only_whitespace = lambda {
input = """



"""
assert outdent(input) == "", "Only whitespace test failed"
}

0 comments on commit 9efb46c

Please sign in to comment.