36 Commits

Author SHA1 Message Date
github-actions[bot]
d1148580df chore(main): release 1.1.2 (#12)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-21 01:59:58 +01:00
c3c5f71c7a docs(readme): fix build badge 2024-10-21 01:57:46 +01:00
2e276c037b docs(readme): fix styling of badges 2024-10-21 01:53:54 +01:00
af31c21ec1 Merge pull request #11 from jimeh/perf-improvement
fix(perf): minor improvement when no indent is found
2024-10-21 01:50:25 +01:00
84715b90d0 fix(perf): minor improvement when no indent is found 2024-10-21 01:43:49 +01:00
3878874bbe chore: remove bootstrap values in release-please config 2022-12-05 01:24:42 +00:00
23c6c4cd7d Merge pull request #10 from jimeh/release-please--branches--main 2022-12-05 00:02:42 +00:00
github-actions[bot]
1a0b0aafae chore(main): release 1.1.1 2022-12-05 00:02:03 +00:00
bf5d7b709e ci: release depends on lint, tidy and test 2022-12-05 00:00:58 +00:00
5890256a45 ci(release): fix filename of release-please config 2022-12-04 23:57:41 +00:00
5e31bd0485 Merge pull request #7 from jimeh/improve-performance 2022-12-04 23:55:21 +00:00
178d9b5bf6 perf: simplify line-feed and minimum indentation loops
This is based on performance improvements suggested by OpenAI's ChatGPT.
2022-12-04 23:49:34 +00:00
20ac9c9824 Merge pull request #9 from jimeh/release-please 2022-12-04 23:46:44 +00:00
caeba6291d chore(release): setup release-please for automatic release PR generation 2022-12-04 23:43:14 +00:00
044587fb4c ci(benchmarks): fix store benchmark job 2022-12-04 23:32:55 +00:00
69ffce4dca Merge pull request #8 from jimeh/update-workflow-actions 2022-12-04 23:24:47 +00:00
a0b74d98db chore(deps): update golangci-lint 2022-12-04 23:22:55 +00:00
cf20ee4e75 ci(github): update workflow actions 2022-12-04 23:22:55 +00:00
369ec87ddd chore(release): 1.1.0 2021-02-22 22:56:08 +00:00
5a4b199462 docs(godoc): fix typo in doc string for Print function 2021-02-22 22:51:46 +00:00
86be1bf614 Merge pull request #6 from jimeh/performance-improvements
feat(performance): improve core undenting performance by 20-30x
2021-02-22 22:47:02 +00:00
6a2254e918 feat(performance): improve core undenting performance by around 20-30x
Previously we relied heavily on regexp to filter out and grab all
indentation white space, and then to strip away indentation shared
across all lines. This was reasonably fast. However I wanted to see if I
could make it faster by manually iterating over the input. Turns out
doing so makes is around 20 times faster.

The code is a lot more complicated though, but I'll attempt to break it
down. There's three main phases to it:

1. Iterate over every character of the input to locate all
   line-feed (\n) characters, storing their indexes in a integer slice.
2. Iterate over the list of life-feed indexes, and for each line-feed,
   scan forward until a non-whitespace character is found, counting how
   many whitespace characters we encountered directly after the
   life-feed. If the number is lower than our previously lowest number
   of leading whitespace characters, store that as the new lowest
   number.
3. Now that we know the lowest number of leading whitespace characters
   common across every line of the input, we can iterate over the list
   of life-feed indexes again. This time to build the final output, but
   reading all characters from the life-feed index + whitespace number,
   until the next life-feed character, or end of input.

Overall this approach yields a 15-20x speed improvement over the old
method.

Benchmarks, before:

    goos: darwin
    goarch: amd64
    pkg: github.com/jimeh/undent
    cpu: Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
    BenchmarkBytes/empty-8          78280611                15.18 ns/op
    BenchmarkBytes/single-line-8     2361297               515.1 ns/op
    BenchmarkBytes/single-line_indented-8             317440              3618 ns/op
    BenchmarkBytes/multi-line-8                       630370              1920 ns/op
    BenchmarkBytes/multi-line_space_indented-8        156266              7664 ns/op
    BenchmarkBytes/multi-line_space_indented_without_any_leading_line-breaks-8                155672              8168 ns/op
    BenchmarkBytes/multi-line_space_indented_with_leading_line-breaks-8                       144655              8165 ns/op
    BenchmarkBytes/multi-line_tab_indented-8                                                  206425              5462 ns/op
    BenchmarkBytes/multi-line_tab_indented_without_any_leading_line-breaks-8                  223620              5542 ns/op
    BenchmarkBytes/multi-line_tab_indented_with_leading_line-breaks-8                         208132              5857 ns/op
    BenchmarkBytes/multi-line_tab_indented_with_tabs_and_spaces_after_indent-8                199480              5687 ns/op
    BenchmarkBytes/multi-line_space_indented_with_blank_lines-8                               148402              8072 ns/op
    BenchmarkBytes/multi-line_tab_indented_with_blank_lines-8                                 200929              5691 ns/op
    BenchmarkBytes/multi-line_space_indented_with_random_indentation-8                        197412              6515 ns/op
    BenchmarkBytes/multi-line_tab_indented_with_random_indentation-8                          281493              4272 ns/op
    BenchmarkBytes/long_block_of_text-8                                                         9894            115752 ns/op
    BenchmarkString/empty-8                                                                 100000000               12.75 ns/op
    BenchmarkString/single-line-8                                                            2224165               529.0 ns/op
    BenchmarkString/single-line_indented-8                                                    314088              3784 ns/op
    BenchmarkString/multi-line-8                                                              645804              1968 ns/op
    BenchmarkString/multi-line_space_indented-8                                               149310              8103 ns/op
    BenchmarkString/multi-line_space_indented_without_any_leading_line-breaks-8               145390              8496 ns/op
    BenchmarkString/multi-line_space_indented_with_leading_line-breaks-8                      145579              8161 ns/op
    BenchmarkString/multi-line_tab_indented-8                                                 223596              5487 ns/op
    BenchmarkString/multi-line_tab_indented_without_any_leading_line-breaks-8                 214842              5641 ns/op
    BenchmarkString/multi-line_tab_indented_with_leading_line-breaks-8                        209067              5685 ns/op
    BenchmarkString/multi-line_tab_indented_with_tabs_and_spaces_after_indent-8               210307              5584 ns/op
    BenchmarkString/multi-line_space_indented_with_blank_lines-8                              133948              9280 ns/op
    BenchmarkString/multi-line_tab_indented_with_blank_lines-8                                178296              5769 ns/op
    BenchmarkString/multi-line_space_indented_with_random_indentation-8                       206030              6222 ns/op
    BenchmarkString/multi-line_tab_indented_with_random_indentation-8                         236450              4259 ns/op
    BenchmarkString/long_block_of_text-8                                                       10000            113065 ns/op
    PASS
    ok      github.com/jimeh/undent 44.800s

Benchmarks, after:

    goos: darwin
    goarch: amd64
    pkg: github.com/jimeh/undent
    cpu: Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
    BenchmarkBytes/empty-8          596493562                2.074 ns/op
    BenchmarkBytes/single-line-8    20044598                60.64 ns/op
    BenchmarkBytes/single-line_indented-8           12449749                84.43 ns/op
    BenchmarkBytes/multi-line-8                      5086376               232.3 ns/op
    BenchmarkBytes/multi-line_space_indented-8       3077774               400.4 ns/op
    BenchmarkBytes/multi-line_space_indented_without_any_leading_line-breaks-8               3011881               386.6 ns/op
    BenchmarkBytes/multi-line_space_indented_with_leading_line-breaks-8                      3034299               402.9 ns/op
    BenchmarkBytes/multi-line_tab_indented-8                                                 4500271               266.2 ns/op
    BenchmarkBytes/multi-line_tab_indented_without_any_leading_line-breaks-8                 4355886               277.5 ns/op
    BenchmarkBytes/multi-line_tab_indented_with_leading_line-breaks-8                        3758012               289.5 ns/op
    BenchmarkBytes/multi-line_tab_indented_with_tabs_and_spaces_after_indent-8               4425787               271.9 ns/op
    BenchmarkBytes/multi-line_space_indented_with_blank_lines-8                              3035809               412.2 ns/op
    BenchmarkBytes/multi-line_tab_indented_with_blank_lines-8                                3771512               334.2 ns/op
    BenchmarkBytes/multi-line_space_indented_with_random_indentation-8                       4461404               275.6 ns/op
    BenchmarkBytes/multi-line_tab_indented_with_random_indentation-8                         6960343               174.6 ns/op
    BenchmarkBytes/long_block_of_text-8                                                       315788              3776 ns/op
    BenchmarkString/empty-8                                                                 338024905                3.761 ns/op
    BenchmarkString/single-line-8                                                           20067831                59.28 ns/op
    BenchmarkString/single-line_indented-8                                                  13826002                88.16 ns/op
    BenchmarkString/multi-line-8                                                             4451938               261.6 ns/op
    BenchmarkString/multi-line_space_indented-8                                              2911797               411.1 ns/op
    BenchmarkString/multi-line_space_indented_without_any_leading_line-breaks-8              2699631               416.5 ns/op
    BenchmarkString/multi-line_space_indented_with_leading_line-breaks-8                     2737174               436.3 ns/op
    BenchmarkString/multi-line_tab_indented-8                                                4208000               304.6 ns/op
    BenchmarkString/multi-line_tab_indented_without_any_leading_line-breaks-8                4029422               295.8 ns/op
    BenchmarkString/multi-line_tab_indented_with_leading_line-breaks-8                       3929960               310.3 ns/op
    BenchmarkString/multi-line_tab_indented_with_tabs_and_spaces_after_indent-8              3978992               292.5 ns/op
    BenchmarkString/multi-line_space_indented_with_blank_lines-8                             2829766               428.5 ns/op
    BenchmarkString/multi-line_tab_indented_with_blank_lines-8                               3788185               304.8 ns/op
    BenchmarkString/multi-line_space_indented_with_random_indentation-8                      4104337               279.4 ns/op
    BenchmarkString/multi-line_tab_indented_with_random_indentation-8                        7092417               177.4 ns/op
    BenchmarkString/long_block_of_text-8                                                      283140              4398 ns/op
    PASS
    ok      github.com/jimeh/undent 47.252s
2021-02-22 22:42:27 +00:00
98946bf286 docs(readme): fix main description 2021-02-21 04:03:48 +00:00
f0855f3a83 chore(git): update "master" branch references to "main" 2021-02-21 03:45:19 +00:00
c3e2bd98b0 Merge pull request #5 from jimeh/add-print-funcs
feat(print) add Print, Printf, Fprint, and Fprintf functions
2021-02-21 00:10:54 +00:00
fe6ba9c1c4 chore(deps): update golangci-lint to v1.37.x 2021-02-20 22:09:49 +00:00
d1c5735041 chore(makefile): minor cleanup and tweaks 2021-02-20 22:09:49 +00:00
5cae4bc420 feat(print) add Print, Printf, Fprint, and Fprintf functions 2021-02-20 22:09:49 +00:00
4ded03bd72 chore(release): 1.0.2 2020-12-14 14:55:43 +00:00
68a97519d5 Merge pull request #4 from jimeh/fix-bytes-method
fix(bytes): change Bytes function to accept string input but return a byte slice
2020-12-14 14:55:04 +00:00
5dbdbbf341 fix(bytes): change Bytes function to accept string input but return a byte slice
The old method signature was just nonsensical, as you would always be
providing indented values via a string literal. So it makes much more
sense to have all methods accept a string argument, and then return
different types.

This also allows use of a `Bytesf` method.

This is technically a breaking change, but I'm classifying it as a
bugfix cause the old method signature was basically useless.
2020-12-14 14:52:32 +00:00
d79e413e8e chore(release): 1.0.1 2020-12-07 10:48:40 +00:00
cc372da881 Merge pull request #3 from jimeh/remove-leading-line-break-on-undented-values
fix(whitespace): remove leading line-break from input
2020-12-07 10:46:31 +00:00
b2057429a1 fix(whitespace): remove leading line-break from input
This effectively cleans up what I consider syntactical sugar required
due to Go's syntax. For example:

    str := undent.String(`
        hello
        world`,
    )

In the above example I would consider the initial line-break after the
opening back-tick (`) character syntactical sugar, and hence should be
discarded from the final undented string.

However if the literal string contains more than one initial line-break,
only the first one should be removed, as the rest would intentionally be
part of the input.
2020-12-07 10:43:26 +00:00
24e64f6c39 docs(readme): fix readme description to match godoc description 2020-11-26 12:42:41 +00:00
30dba69951 docs(readme): add Benchmarks section, update Go Reference link 2020-11-26 12:32:58 +00:00
12 changed files with 727 additions and 156 deletions

View File

@@ -7,11 +7,14 @@ jobs:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
version: v1.31
go-version: 1.15
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.50
env:
VERBOSE: "true"
@@ -19,11 +22,11 @@ jobs:
name: Tidy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.15
- uses: actions/cache@v2
- uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
@@ -35,13 +38,13 @@ jobs:
benchmark:
name: Benchmarks
runs-on: ubuntu-latest
if: github.ref != 'refs/heads/master'
if: github.ref != 'refs/heads/main'
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.15
- uses: actions/cache@v2
- uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
@@ -67,18 +70,18 @@ jobs:
name: Coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.15
- uses: actions/cache@v2
- uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Publish coverage
uses: paambaati/codeclimate-action@v2.7.4
uses: paambaati/codeclimate-action@v3.2.0
env:
VERBOSE: "true"
GOMAXPROCS: 4
@@ -93,11 +96,11 @@ jobs:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.15
- uses: actions/cache@v2
- uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
@@ -111,13 +114,13 @@ jobs:
benchmark-store:
name: Store benchmarks
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- uses: actions/checkout@v3
- uses: actions/setup-go@v3
with:
go-version: 1.15
- uses: actions/cache@v2
- uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
@@ -134,6 +137,16 @@ jobs:
with:
tool: "go"
output-file-path: output.txt
github-token: ${{ secrets.GH_PUSH_TOKEN }}
github-token: ${{ secrets.GITHUB_TOKEN }}
comment-on-alert: true
auto-push: true
release-please:
needs: [lint, tidy, test]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: google-github-actions/release-please-action@v3
id: release-please
with:
command: manifest

View File

@@ -7,8 +7,9 @@ linters-settings:
golint:
min-confidence: 0
govet:
check-shadowing: true
enable-all: true
disable:
- fieldalignment
lll:
line-length: 80
tab-width: 4
@@ -21,10 +22,10 @@ linters:
disable-all: true
enable:
- bodyclose
- deadcode
- depguard
- dupl
- errcheck
- exportloopref
- funlen
- gochecknoinits
- goconst
@@ -32,7 +33,6 @@ linters:
- gocyclo
- goerr113
- goimports
- golint
- goprintffuncname
- gosec
- gosimple
@@ -44,19 +44,15 @@ linters:
- nlreturn
- noctx
- nolintlint
- scopelint
- revive
- sqlclosecheck
- staticcheck
- structcheck
- typecheck
- unconvert
- unused
- varcheck
- whitespace
issues:
include:
# - EXC0002 # disable excluding of issues about comments from golint
exclude:
- Using the variable on range scope `tt` in function literal
- Using the variable on range scope `tc` in function literal

View File

@@ -0,0 +1,3 @@
{
".": "1.1.2"
}

View File

@@ -1,6 +1,40 @@
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [1.1.2](https://github.com/jimeh/undent/compare/v1.1.1...v1.1.2) (2024-10-21)
### Bug Fixes
* **perf:** minor improvement when no indent is found ([84715b9](https://github.com/jimeh/undent/commit/84715b90d000292e4e4fbe081e00a583acf0dada))
## [1.1.1](https://github.com/jimeh/undent/compare/v1.1.0...v1.1.1) (2022-12-05)
### Performance Improvements
* simplify line-feed and minimum indentation loops ([178d9b5](https://github.com/jimeh/undent/commit/178d9b5bf6dd090a406229e862c5da1ba26cbf5d))
## [1.1.0](https://github.com/jimeh/undent/compare/v1.0.2...v1.1.0) (2021-02-22)
### Features
* **performance:** improve core undenting performance by around 20-30x ([6a2254e](https://github.com/jimeh/undent/commit/6a2254e918944e5ead4d5a4d6d1b95b0e971c4b7))
* **print** add Print, Printf, Fprint, and Fprintf functions ([5cae4bc](https://github.com/jimeh/undent/commit/5cae4bc420f7bec12efd6071149eac88c37cfd9f))
### [1.0.2](https://github.com/jimeh/undent/compare/v1.0.1...v1.0.2) (2020-12-14)
### Bug Fixes
* **bytes:** change Bytes function to accept string input but return a byte slice ([5dbdbbf](https://github.com/jimeh/undent/commit/5dbdbbf3416b024aac8fca4e218802d6ad49ea74))
### [1.0.1](https://github.com/jimeh/undent/compare/v1.0.0...v1.0.1) (2020-12-07)
### Bug Fixes
* **whitespace:** remove leading line-break from input ([b205742](https://github.com/jimeh/undent/commit/b2057429a1181724ae50acaed26fe434231362b4))
## 1.0.0 (2020-11-26)

View File

@@ -1,3 +1,4 @@
GOMODNAME := $(shell grep 'module' go.mod | sed -e 's/^module //')
SOURCES := $(shell find . -name "*.go" -or -name "go.mod" -or -name "go.sum" \
-or -name "Makefile")
@@ -18,7 +19,7 @@ SHELL ?= /bin/bash
SHELL := env \
GO111MODULE=on \
GOBIN=$(CURDIR)/$(TOOLDIR) \
CGO_ENABLED=1 \
CGO_ENABLED=0 \
PATH='$(CURDIR)/$(BINDIR):$(CURDIR)/$(TOOLDIR):$(PATH)' \
$(SHELL)
@@ -34,7 +35,6 @@ SHELL := env \
#
TOOLS += $(TOOLDIR)/gobin
gobin: $(TOOLDIR)/gobin
$(TOOLDIR)/gobin:
GO111MODULE=off go get -u github.com/myitcv/gobin
@@ -42,16 +42,13 @@ $(TOOLDIR)/gobin:
define tool # 1: binary-name, 2: go-import-path
TOOLS += $(TOOLDIR)/$(1)
.PHONY: $(1)
$(1): $(TOOLDIR)/$(1)
$(TOOLDIR)/$(1): $(TOOLDIR)/gobin Makefile
gobin $(V) "$(2)"
endef
$(eval $(call tool,godoc,golang.org/x/tools/cmd/godoc))
$(eval $(call tool,gofumports,mvdan.cc/gofumpt/gofumports))
$(eval $(call tool,golangci-lint,github.com/golangci/golangci-lint/cmd/golangci-lint@v1.31))
$(eval $(call tool,golangci-lint,github.com/golangci/golangci-lint/cmd/golangci-lint@v1.50))
.PHONY: tools
tools: $(TOOLS)
@@ -75,25 +72,18 @@ clean-golden:
.PHONY: test
test:
go test $(V) -count=1 -race $(TESTARGS) $(TEST)
.PHONY: test-update-golden
test-update-golden:
@$(MAKE) test UPDATE_GOLDEN=1
.PHONY: regen-golden
regen-golden: clean-golden test-update-golden
CGO_ENABLED=1 go test $(V) -count=1 -race $(TESTARGS) $(TEST)
.PHONY: test-deps
test-deps:
go test all
.PHONY: lint
lint: golangci-lint
lint: $(TOOLDIR)/golangci-lint
GOGC=off golangci-lint $(V) run
.PHONY: format
format: gofumports
format: $(TOOLDIR)/gofumports
gofumports -w .
.SILENT: bench
@@ -161,7 +151,8 @@ check-tidy:
# Serve docs
.PHONY: docs
docs: godoc
docs: $(TOOLDIR)/godoc
$(info serving docs on http://127.0.0.1:6060/pkg/$(GOMODNAME)/)
@godoc -http=127.0.0.1:6060
#

View File

@@ -4,35 +4,18 @@
<p align="center">
<strong>
Go package which removes leading indentation/white-space from multi-line
strings and byte slices.
Go package which removes leading indentation/white-space from strings.
</strong>
</p>
<p align="center">
<a href="https://pkg.go.dev/github.com/jimeh/undent">
<img src="https://img.shields.io/badge/%E2%80%8B-reference-387b97.svg?logo=go&logoColor=white"
alt="Go Reference">
</a>
<a href="https://github.com/jimeh/undent/releases">
<img src="https://img.shields.io/github/v/tag/jimeh/undent?label=release" alt="GitHub tag (latest SemVer)">
</a>
<a href="https://github.com/jimeh/undent/actions">
<img src="https://img.shields.io/github/workflow/status/jimeh/undent/CI.svg?logo=github" alt="Actions Status">
</a>
<a href="https://codeclimate.com/github/jimeh/undent">
<img src="https://img.shields.io/codeclimate/coverage/jimeh/undent.svg?logo=code%20climate" alt="Coverage">
</a>
<a href="https://github.com/jimeh/undent/issues">
<img src="https://img.shields.io/github/issues-raw/jimeh/undent.svg?style=flat&logo=github&logoColor=white"
alt="GitHub issues">
</a>
<a href="https://github.com/jimeh/undent/pulls">
<img src="https://img.shields.io/github/issues-pr-raw/jimeh/undent.svg?style=flat&logo=github&logoColor=white" alt="GitHub pull requests">
</a>
<a href="https://github.com/jimeh/undent/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/jimeh/undent.svg?style=flat" alt="License Status">
</a>
<a href="https://pkg.go.dev/github.com/jimeh/undent"><img src="https://img.shields.io/badge/%E2%80%8B-reference-387b97.svg?logo=go&logoColor=white" alt="Go Reference"></a>
<a href="https://github.com/jimeh/undent/releases"><img src="https://img.shields.io/github/v/tag/jimeh/undent?label=release" alt="GitHub tag (latest SemVer)"></a>
<a href="https://github.com/jimeh/undent/actions"><img src="https://img.shields.io/github/actions/workflow/status/jimeh/undent/ci.yml?logo=github" alt="Actions Status"></a>
<a href="https://codeclimate.com/github/jimeh/undent"><img src="https://img.shields.io/codeclimate/coverage/jimeh/undent.svg?logo=code%20climate" alt="Coverage"></a>
<a href="https://github.com/jimeh/undent/issues"><img src="https://img.shields.io/github/issues-raw/jimeh/undent.svg?style=flat&logo=github&logoColor=white" alt="GitHub issues"></a>
<a href="https://github.com/jimeh/undent/pulls"><img src="https://img.shields.io/github/issues-pr-raw/jimeh/undent.svg?style=flat&logo=github&logoColor=white" alt="GitHub pull requests"></a>
<a href="https://github.com/jimeh/undent/blob/main/LICENSE"><img src="https://img.shields.io/github/license/jimeh/undent.svg?style=flat" alt="License Status"></a>
</p>
```go
@@ -52,9 +35,15 @@ fmt.Println(s)
## Documentation
Please see the [Go Reference](https://pkg.go.dev/github.com/jimeh/undent) for
documentation and examples.
Please see the
[Go Reference](https://pkg.go.dev/github.com/jimeh/undent#section-documentation)
for documentation and examples.
## Benchmarks
Benchmark reports and graphs are available here:
https://jimeh.me/undent/dev/bench/
## License
[MIT](https://github.com/jimeh/undent/blob/master/LICENSE)
[MIT](https://github.com/jimeh/undent/blob/main/LICENSE)

5
go.mod
View File

@@ -2,4 +2,7 @@ module github.com/jimeh/undent
go 1.15
require github.com/stretchr/testify v1.6.1
require (
github.com/rhysd/go-fakeio v1.0.0
github.com/stretchr/testify v1.6.1
)

2
go.sum
View File

@@ -2,6 +2,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rhysd/go-fakeio v1.0.0 h1:+TjiKCOs32dONY7DaoVz/VPOdvRkPfBkEyUDIpM8FQY=
github.com/rhysd/go-fakeio v1.0.0/go.mod h1:joYxF906trVwp2JLrE4jlN7A0z6wrz8O6o1UjarbFzE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=

View File

@@ -0,0 +1,14 @@
{
"release-type": "go",
"bump-minor-pre-major": true,
"bump-patch-for-minor-pre-major": true,
"packages": {
".": {
"changelog-path": "CHANGELOG.md",
"draft": false,
"prerelease": false,
"extra-files": []
}
},
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json"
}

144
undent.go
View File

@@ -4,65 +4,86 @@ package undent
import (
"fmt"
"regexp"
"io"
"strings"
)
var matcher = regexp.MustCompile(`(?m)^([ \t]*)(?:\S)`)
const (
tab = 9
lf = 10
spc = 32
)
// Bytes removes leading indentation/white-space from given byte slice.
func Bytes(b []byte) []byte {
matches := matcher.FindAll(b, -1)
if len(matches) == 0 {
return b
// Bytes removes leading indentation/white-space from given string and returns
// it as a byte slice.
func Bytes(s string) []byte {
if len(s) == 0 {
return []byte{}
}
index := 0
length := len(matches[0])
// find smallest indent relative to each line-feed
min := -1
count := 0
for i, s := range matches[1:] {
l := len(s)
if l < length {
index = i + 1
length = l
lfs := make([]int, 0, strings.Count(s, "\n"))
if s[0] != lf {
lfs = append(lfs, -1)
}
indent := 0
for i := 0; i < len(s); i++ {
if s[i] == lf {
lfs = append(lfs, i)
indent = 0
} else if indent < min || min == -1 {
switch s[i] {
case spc, tab:
indent++
default:
if indent > 0 {
count++
}
if indent < min || min == -1 {
min = indent
}
}
}
}
if length <= 1 {
return b
if min == -1 {
return []byte(s)
}
indent := matches[index][0 : length-1]
return regexp.MustCompile(
`(?m)^`+regexp.QuoteMeta(string(indent)),
).ReplaceAllLiteral(b, []byte{})
// extract each line without indentation
out := make([]byte, 0, len(s)-(min*count))
for i := 0; i < len(lfs); i++ {
offset := lfs[i] + 1
end := len(s)
if i+1 < len(lfs) {
end = lfs[i+1] + 1
}
if offset+min < end {
out = append(out, s[offset+min:end]...)
} else if offset < end {
out = append(out, s[offset:end]...)
}
}
return out
}
// Bytesf removes leading indentation/white-space from given format string
// before passing format and all additional arguments to fmt.Sprintf, returning
// the result as a byte slice.
func Bytesf(format string, a ...interface{}) []byte {
return []byte(Stringf(format, a...))
}
// String removes leading indentation/white-space from given string.
func String(s string) string {
matches := matcher.FindAllString(s, -1)
if len(matches) == 0 {
return s
}
index := 0
length := len(matches[0])
for i, s := range matches[1:] {
l := len(s)
if l < length {
index = i + 1
length = l
}
}
if length <= 1 {
return s
}
indent := matches[index][0 : length-1]
return regexp.MustCompile(
`(?m)^`+regexp.QuoteMeta(indent),
).ReplaceAllLiteralString(s, "")
return string(Bytes(s))
}
// Stringf removes leading indentation/white-space from given format string
@@ -71,3 +92,38 @@ func String(s string) string {
func Stringf(format string, a ...interface{}) string {
return fmt.Sprintf(String(format), a...)
}
// Print will undent any string arguments before passing them to fmt.Print.
func Print(a ...interface{}) (n int, err error) {
return fmt.Print(undentInterfaces(a)...)
}
// Printf will undent the given format string before passing it and all
// arguments to fmt.Printf.
func Printf(format string, a ...interface{}) (n int, err error) {
return fmt.Printf(String(format), a...)
}
// Fprint will undent any string arguments before passing them to fmt.Fprint.
func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
return fmt.Fprint(w, undentInterfaces(a)...)
}
// Fprintf will undent the given format string before passing it and all
// arguments to fmt.Fprintf.
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
return fmt.Fprintf(w, String(format), a...)
}
func undentInterfaces(a []interface{}) []interface{} {
var r []interface{}
for _, v := range a {
if s, ok := v.(string); ok {
v = String(s)
}
r = append(r, v)
}
return r
}

View File

@@ -1,21 +1,35 @@
package undent_test
import (
"bytes"
"fmt"
"github.com/jimeh/undent"
)
func ExampleBytes() {
b := undent.Bytes([]byte(`
b := undent.Bytes(`
{
"hello": "world"
}`,
))
)
fmt.Println(string(b))
// Output:
//
// {
// "hello": "world"
// }
}
func ExampleBytesf() {
s := undent.Bytesf(`
{
"hello": "%s"
}`,
"world",
)
fmt.Println(string(s))
// Output:
// {
// "hello": "world"
// }
@@ -29,7 +43,6 @@ func ExampleString() {
)
fmt.Println(s)
// Output:
//
// {
// "hello": "world"
// }
@@ -44,7 +57,60 @@ func ExampleStringf() {
)
fmt.Println(s)
// Output:
//
// {
// "hello": "world"
// }
}
func ExamplePrint() {
undent.Print(`
{
"hello": "world"
}`,
)
// Output:
// {
// "hello": "world"
// }
}
func ExamplePrintf() {
undent.Printf(`
{
"hello": "%s"
}`,
"world",
)
// Output:
// {
// "hello": "world"
// }
}
func ExampleFprint() {
var buf bytes.Buffer
undent.Fprint(&buf, `
{
"hello": "world"
}`,
)
fmt.Println(buf.String())
// Output:
// {
// "hello": "world"
// }
}
func ExampleFprintf() {
var buf bytes.Buffer
undent.Fprintf(&buf, `
{
"hello": "%s"
}`,
"world",
)
fmt.Println(buf.String())
// Output:
// {
// "hello": "world"
// }

View File

@@ -1,9 +1,12 @@
package undent
import (
"bytes"
"testing"
"github.com/rhysd/go-fakeio"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var stringTestCases = []struct {
@@ -35,8 +38,7 @@ var stringTestCases = []struct {
"bar"
]
}`,
want: `
{
want: `{
"hello": "world",
"foo": [
"bar"
@@ -46,6 +48,39 @@ var stringTestCases = []struct {
{
name: "multi-line space indented",
s: `
{
"hello": "world",
"foo": [
"bar"
]
}`,
want: `{
"hello": "world",
"foo": [
"bar"
]
}`,
},
{
name: "multi-line space indented without any leading line-breaks",
s: ` {
"hello": "world",
"foo": [
"bar"
]
}`,
want: `{
"hello": "world",
"foo": [
"bar"
]
}`,
},
{
name: "multi-line space indented with leading line-breaks",
s: `
{
"hello": "world",
"foo": [
@@ -53,6 +88,7 @@ var stringTestCases = []struct {
]
}`,
want: `
{
"hello": "world",
"foo": [
@@ -63,6 +99,39 @@ var stringTestCases = []struct {
{
name: "multi-line tab indented",
s: `
{
"hello": "world",
"foo": [
"bar"
]
}`,
want: `{
"hello": "world",
"foo": [
"bar"
]
}`,
},
{
name: "multi-line tab indented without any leading line-breaks",
s: ` {
"hello": "world",
"foo": [
"bar"
]
}`,
want: `{
"hello": "world",
"foo": [
"bar"
]
}`,
},
{
name: "multi-line tab indented with leading line-breaks",
s: `
{
"hello": "world",
"foo": [
@@ -70,6 +139,7 @@ var stringTestCases = []struct {
]
}`,
want: `
{
"hello": "world",
"foo": [
@@ -86,8 +156,7 @@ var stringTestCases = []struct {
"bar"
]
}`,
want: `
{
want: `{
"hello": "world",
"foo": [
"bar"
@@ -105,8 +174,7 @@ var stringTestCases = []struct {
]
}`,
want: `
{
want: `{
"hello": "world",
"foo": [
@@ -126,8 +194,7 @@ var stringTestCases = []struct {
]
}`,
want: `
{
want: `{
"hello": "world",
"foo": [
@@ -143,8 +210,7 @@ var stringTestCases = []struct {
world
foo
bar`,
want: `
hello
want: ` hello
world
foo
bar`,
@@ -156,12 +222,113 @@ world
world
foo
bar`,
want: `
hello
want: ` hello
world
foo
bar`,
},
{
name: "long block of text",
s: `
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc
ornare, tellus vel luctus tristique, ipsum ante varius mauris, non
hendrerit tellus urna quis ex. Donec efficitur arcu sed iaculis
lobortis. Phasellus facilisis vitae mi quis accumsan. Suspendisse
rhoncus viverra odio ultricies rhoncus. Cras laoreet tortor
vestibulum pharetra luctus. Vivamus sit amet volutpat elit.
Suspendisse feugiat lectus id arcu sollicitudin tincidunt. Duis ut
sem auctor orci sodales varius in ac odio. Nullam finibus odio at
lacus tristique malesuada.
Morbi nisl nulla, euismod eu enim in, tincidunt varius turpis. Morbi
ullamcorper tortor mi, ut aliquam metus posuere vel. Etiam vel dui
at quam placerat sollicitudin. Proin aliquam justo vitae mauris
gravida porta. Praesent hendrerit egestas ligula, faucibus tincidunt
tortor aliquet at. Ut luctus vehicula arcu eget cursus. Suspendisse
eget enim mollis, condimentum lacus eu, viverra nulla. Aenean vel
sapien eget enim convallis accumsan. Donec dictum ullamcorper leo
placerat sollicitudin. Pellentesque habitant morbi tristique
senectus et netus et malesuada fames ac turpis egestas. Vestibulum
volutpat mattis est, a feugiat purus feugiat at. Quisque at velit ut
mauris convallis sodales a et erat. Mauris condimentum augue sit
amet arcu sodales, aliquet ultrices ipsum tempor. Donec scelerisque
mi ligula, vel volutpat velit posuere a. Sed faucibus dui pulvinar
lorem commodo egestas. In facilisis suscipit lacus non suscipit.
Nunc dictum est nulla, a rhoncus mi posuere id. Morbi at tempus
augue. Quisque ac nibh auctor velit auctor placerat id non eros.
Nulla condimentum quam id risus suscipit, ut fermentum mauris
lacinia. Vestibulum suscipit rutrum ex, sed vulputate nisi tempus
ultricies. Sed id ante pretium, accumsan sapien eget, malesuada
quam. Phasellus quis commodo enim. Vivamus in purus ac lorem ornare
posuere non eu quam. Sed arcu tortor, gravida quis fringilla nec,
ultricies et sem. Pellentesque arcu enim, tempor id nisl at, rhoncus
efficitur sem. Ut quis placerat quam. Donec maximus a risus sed
posuere. Curabitur pretium a diam non aliquet.
Class aptent taciti sociosqu ad litora torquent per conubia nostra,
per inceptos himenaeos. Morbi volutpat felis leo, vel ultrices orci
bibendum ac. Integer eu mattis urna. Donec dictum vehicula
fermentum. Pellentesque a rutrum ipsum. Donec ultricies elit purus,
eget viverra tellus tristique sed. In hac habitasse platea dictumst.
Duis elementum semper elit, sit amet rhoncus lacus dictum ac. Nunc
pretium enim ac urna efficitur, eget facilisis enim interdum.
Vivamus vel lectus lacus. Praesent vestibulum vel ligula eget
cursus. Quisque eu dignissim erat. Quisque maximus arcu eu turpis
pulvinar egestas. Nam aliquet neque sed tellus finibus mollis.
Phasellus consequat nibh nec ornare egestas. Donec at pellentesque
lorem.`,
want: `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc
ornare, tellus vel luctus tristique, ipsum ante varius mauris, non
hendrerit tellus urna quis ex. Donec efficitur arcu sed iaculis
lobortis. Phasellus facilisis vitae mi quis accumsan. Suspendisse
rhoncus viverra odio ultricies rhoncus. Cras laoreet tortor
vestibulum pharetra luctus. Vivamus sit amet volutpat elit.
Suspendisse feugiat lectus id arcu sollicitudin tincidunt. Duis ut
sem auctor orci sodales varius in ac odio. Nullam finibus odio at
lacus tristique malesuada.
Morbi nisl nulla, euismod eu enim in, tincidunt varius turpis. Morbi
ullamcorper tortor mi, ut aliquam metus posuere vel. Etiam vel dui
at quam placerat sollicitudin. Proin aliquam justo vitae mauris
gravida porta. Praesent hendrerit egestas ligula, faucibus tincidunt
tortor aliquet at. Ut luctus vehicula arcu eget cursus. Suspendisse
eget enim mollis, condimentum lacus eu, viverra nulla. Aenean vel
sapien eget enim convallis accumsan. Donec dictum ullamcorper leo
placerat sollicitudin. Pellentesque habitant morbi tristique
senectus et netus et malesuada fames ac turpis egestas. Vestibulum
volutpat mattis est, a feugiat purus feugiat at. Quisque at velit ut
mauris convallis sodales a et erat. Mauris condimentum augue sit
amet arcu sodales, aliquet ultrices ipsum tempor. Donec scelerisque
mi ligula, vel volutpat velit posuere a. Sed faucibus dui pulvinar
lorem commodo egestas. In facilisis suscipit lacus non suscipit.
Nunc dictum est nulla, a rhoncus mi posuere id. Morbi at tempus
augue. Quisque ac nibh auctor velit auctor placerat id non eros.
Nulla condimentum quam id risus suscipit, ut fermentum mauris
lacinia. Vestibulum suscipit rutrum ex, sed vulputate nisi tempus
ultricies. Sed id ante pretium, accumsan sapien eget, malesuada
quam. Phasellus quis commodo enim. Vivamus in purus ac lorem ornare
posuere non eu quam. Sed arcu tortor, gravida quis fringilla nec,
ultricies et sem. Pellentesque arcu enim, tempor id nisl at, rhoncus
efficitur sem. Ut quis placerat quam. Donec maximus a risus sed
posuere. Curabitur pretium a diam non aliquet.
Class aptent taciti sociosqu ad litora torquent per conubia nostra,
per inceptos himenaeos. Morbi volutpat felis leo, vel ultrices orci
bibendum ac. Integer eu mattis urna. Donec dictum vehicula
fermentum. Pellentesque a rutrum ipsum. Donec ultricies elit purus,
eget viverra tellus tristique sed. In hac habitasse platea dictumst.
Duis elementum semper elit, sit amet rhoncus lacus dictum ac. Nunc
pretium enim ac urna efficitur, eget facilisis enim interdum.
Vivamus vel lectus lacus. Praesent vestibulum vel ligula eget
cursus. Quisque eu dignissim erat. Quisque maximus arcu eu turpis
pulvinar egestas. Nam aliquet neque sed tellus finibus mollis.
Phasellus consequat nibh nec ornare egestas. Donec at pellentesque
lorem.`,
},
}
var stringfTestCases = []struct {
@@ -197,8 +364,7 @@ var stringfTestCases = []struct {
]
}`,
a: []interface{}{"world", 42},
want: `
{
want: `{
"hello": "world",
"foo": [
42
@@ -208,6 +374,41 @@ var stringfTestCases = []struct {
{
name: "multi-line space indented",
s: `
{
"hello": "%s",
"foo": [
%d
]
}`,
a: []interface{}{"world", 42},
want: `{
"hello": "world",
"foo": [
42
]
}`,
},
{
name: "multi-line space indented without any leading line-breaks",
s: ` {
"hello": "%s",
"foo": [
%d
]
}`,
a: []interface{}{"world", 42},
want: `{
"hello": "world",
"foo": [
42
]
}`,
},
{
name: "multi-line space indented with leading line-breaks",
s: `
{
"hello": "%s",
"foo": [
@@ -216,6 +417,7 @@ var stringfTestCases = []struct {
}`,
a: []interface{}{"world", 42},
want: `
{
"hello": "world",
"foo": [
@@ -233,7 +435,43 @@ var stringfTestCases = []struct {
]
}`,
a: []interface{}{"world", 42},
want: `{
"hello": "world",
"foo": [
42
]
}`,
},
{
name: "multi-line tab indented without any leading line-breaks",
s: ` {
"hello": "%s",
"foo": [
%d
]
}`,
a: []interface{}{"world", 42},
want: `{
"hello": "world",
"foo": [
42
]
}`,
},
{
name: "multi-line tab indented with leading line-breaks",
s: `
{
"hello": "%s",
"foo": [
%d
]
}`,
a: []interface{}{"world", 42},
want: `
{
"hello": "world",
"foo": [
@@ -251,8 +489,7 @@ var stringfTestCases = []struct {
]
}`,
a: []interface{}{"world", 42},
want: `
{
want: `{
"hello": "world",
"foo": [
42
@@ -271,8 +508,7 @@ var stringfTestCases = []struct {
]
}`,
a: []interface{}{"world", 42},
want: `
{
want: `{
"hello": "world",
"foo": [
@@ -293,8 +529,7 @@ var stringfTestCases = []struct {
]
}`,
a: []interface{}{"world", 42},
want: `
{
want: `{
"hello": "world",
"foo": [
@@ -311,8 +546,7 @@ var stringfTestCases = []struct {
foo
%d`,
a: []interface{}{"world", 42},
want: `
hello
want: ` hello
world
foo
42`,
@@ -325,20 +559,134 @@ world
foo
%d`,
a: []interface{}{"world", 42},
want: `
hello
want: ` hello
world
foo
42`,
},
{
name: "long block of text",
s: `
Lorem %s dolor sit amet, consectetur adipiscing elit. Nunc
ornare, tellus vel luctus tristique, ipsum ante varius mauris, non
hendrerit tellus urna quis ex. %s efficitur arcu sed iaculis
lobortis. Phasellus facilisis vitae mi quis accumsan. Suspendisse
rhoncus viverra odio ultricies rhoncus. Cras laoreet tortor
vestibulum pharetra luctus. Vivamus sit amet volutpat elit.
Suspendisse feugiat lectus id arcu sollicitudin tincidunt. Duis ut
sem auctor orci sodales varius in ac odio. Nullam finibus odio at
lacus tristique malesuada.
Morbi nisl nulla, euismod eu enim in, tincidunt varius turpis. Morbi
ullamcorper tortor mi, ut aliquam metus posuere vel. Etiam vel dui
at quam placerat sollicitudin. Proin aliquam justo vitae mauris
gravida porta. Praesent hendrerit egestas ligula, faucibus tincidunt
tortor aliquet at. Ut luctus vehicula arcu eget cursus. Suspendisse
eget enim mollis, condimentum lacus eu, viverra nulla. Aenean vel
sapien eget enim convallis accumsan. Donec dictum ullamcorper leo
placerat sollicitudin. Pellentesque habitant morbi tristique
senectus et netus et malesuada fames ac turpis egestas. Vestibulum
volutpat mattis est, a feugiat purus feugiat at. Quisque at velit ut
mauris convallis sodales a et erat. Mauris condimentum augue sit
amet arcu sodales, aliquet ultrices ipsum tempor. Donec scelerisque
mi ligula, vel volutpat velit posuere a. Sed faucibus dui pulvinar
lorem commodo egestas. In facilisis suscipit lacus non suscipit.
Nunc dictum est nulla, a rhoncus mi posuere id. Morbi at tempus
augue. Quisque ac nibh auctor velit auctor placerat id non eros.
Nulla condimentum quam id risus suscipit, ut fermentum mauris
lacinia. Vestibulum suscipit rutrum ex, sed vulputate nisi tempus
ultricies. Sed id ante pretium, accumsan sapien eget, malesuada
quam. Phasellus quis commodo enim. Vivamus in purus ac lorem ornare
posuere non eu quam. Sed arcu tortor, gravida quis fringilla nec,
ultricies et sem. Pellentesque arcu enim, tempor id nisl at, rhoncus
efficitur sem. Ut quis placerat quam. Donec maximus a risus sed
posuere. Curabitur pretium a diam non aliquet.
Class aptent taciti sociosqu ad litora torquent per conubia nostra,
per inceptos himenaeos. Morbi volutpat felis leo, vel ultrices orci
bibendum ac. Integer eu mattis urna. Donec dictum vehicula
fermentum. Pellentesque a rutrum ipsum. Donec ultricies elit purus,
eget viverra tellus tristique sed. In hac habitasse platea dictumst.
Duis elementum semper elit, sit amet rhoncus lacus dictum ac. Nunc
pretium enim ac urna efficitur, eget facilisis enim interdum.
Vivamus vel lectus lacus. Praesent vestibulum vel ligula eget
cursus. Quisque eu dignissim erat. Quisque maximus arcu eu turpis
pulvinar egestas. Nam aliquet neque sed tellus finibus mollis.
Phasellus consequat nibh nec ornare egestas. Donec at pellentesque
lorem.`,
a: []interface{}{"ipsum", "Donec"},
want: `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc
ornare, tellus vel luctus tristique, ipsum ante varius mauris, non
hendrerit tellus urna quis ex. Donec efficitur arcu sed iaculis
lobortis. Phasellus facilisis vitae mi quis accumsan. Suspendisse
rhoncus viverra odio ultricies rhoncus. Cras laoreet tortor
vestibulum pharetra luctus. Vivamus sit amet volutpat elit.
Suspendisse feugiat lectus id arcu sollicitudin tincidunt. Duis ut
sem auctor orci sodales varius in ac odio. Nullam finibus odio at
lacus tristique malesuada.
Morbi nisl nulla, euismod eu enim in, tincidunt varius turpis. Morbi
ullamcorper tortor mi, ut aliquam metus posuere vel. Etiam vel dui
at quam placerat sollicitudin. Proin aliquam justo vitae mauris
gravida porta. Praesent hendrerit egestas ligula, faucibus tincidunt
tortor aliquet at. Ut luctus vehicula arcu eget cursus. Suspendisse
eget enim mollis, condimentum lacus eu, viverra nulla. Aenean vel
sapien eget enim convallis accumsan. Donec dictum ullamcorper leo
placerat sollicitudin. Pellentesque habitant morbi tristique
senectus et netus et malesuada fames ac turpis egestas. Vestibulum
volutpat mattis est, a feugiat purus feugiat at. Quisque at velit ut
mauris convallis sodales a et erat. Mauris condimentum augue sit
amet arcu sodales, aliquet ultrices ipsum tempor. Donec scelerisque
mi ligula, vel volutpat velit posuere a. Sed faucibus dui pulvinar
lorem commodo egestas. In facilisis suscipit lacus non suscipit.
Nunc dictum est nulla, a rhoncus mi posuere id. Morbi at tempus
augue. Quisque ac nibh auctor velit auctor placerat id non eros.
Nulla condimentum quam id risus suscipit, ut fermentum mauris
lacinia. Vestibulum suscipit rutrum ex, sed vulputate nisi tempus
ultricies. Sed id ante pretium, accumsan sapien eget, malesuada
quam. Phasellus quis commodo enim. Vivamus in purus ac lorem ornare
posuere non eu quam. Sed arcu tortor, gravida quis fringilla nec,
ultricies et sem. Pellentesque arcu enim, tempor id nisl at, rhoncus
efficitur sem. Ut quis placerat quam. Donec maximus a risus sed
posuere. Curabitur pretium a diam non aliquet.
Class aptent taciti sociosqu ad litora torquent per conubia nostra,
per inceptos himenaeos. Morbi volutpat felis leo, vel ultrices orci
bibendum ac. Integer eu mattis urna. Donec dictum vehicula
fermentum. Pellentesque a rutrum ipsum. Donec ultricies elit purus,
eget viverra tellus tristique sed. In hac habitasse platea dictumst.
Duis elementum semper elit, sit amet rhoncus lacus dictum ac. Nunc
pretium enim ac urna efficitur, eget facilisis enim interdum.
Vivamus vel lectus lacus. Praesent vestibulum vel ligula eget
cursus. Quisque eu dignissim erat. Quisque maximus arcu eu turpis
pulvinar egestas. Nam aliquet neque sed tellus finibus mollis.
Phasellus consequat nibh nec ornare egestas. Donec at pellentesque
lorem.`,
},
}
func TestBytes(t *testing.T) {
for _, tt := range stringTestCases {
t.Run(tt.name, func(t *testing.T) {
got := Bytes([]byte(tt.s))
got := Bytes(tt.s)
assert.Equal(t, []byte(tt.want), got)
assert.IsType(t, []byte{}, got)
assert.Equal(t, tt.want, string(got))
})
}
}
func TestBytesf(t *testing.T) {
for _, tt := range stringfTestCases {
t.Run(tt.name, func(t *testing.T) {
got := Bytesf(tt.s, tt.a...)
assert.IsType(t, []byte{}, got)
assert.Equal(t, tt.want, string(got))
})
}
}
@@ -348,6 +696,7 @@ func TestString(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
got := String(tt.s)
assert.IsType(t, "", got)
assert.Equal(t, tt.want, got)
})
}
@@ -358,6 +707,63 @@ func TestStringf(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
got := Stringf(tt.s, tt.a...)
assert.IsType(t, "", got)
assert.Equal(t, tt.want, got)
})
}
}
func TestPrint(t *testing.T) {
for _, tt := range stringTestCases {
t.Run(tt.name, func(t *testing.T) {
got, err := fakeio.Stdout().Do(func() {
_, _ = Print(tt.s, 5, tt.s)
})
require.NoError(t, err)
assert.IsType(t, "", got)
assert.Equal(t, tt.want+"5"+tt.want, got)
})
}
}
func TestPrintf(t *testing.T) {
for _, tt := range stringfTestCases {
t.Run(tt.name, func(t *testing.T) {
got, err := fakeio.Stdout().Do(func() {
_, _ = Printf(tt.s, tt.a...)
})
require.NoError(t, err)
assert.IsType(t, "", got)
assert.Equal(t, tt.want, got)
})
}
}
func TestFprint(t *testing.T) {
for _, tt := range stringTestCases {
t.Run(tt.name, func(t *testing.T) {
var buf bytes.Buffer
_, _ = Fprint(&buf, tt.s, 5, tt.s)
got := buf.String()
assert.IsType(t, "", got)
assert.Equal(t, tt.want+"5"+tt.want, got)
})
}
}
func TestFprintf(t *testing.T) {
for _, tt := range stringfTestCases {
t.Run(tt.name, func(t *testing.T) {
var buf bytes.Buffer
_, _ = Fprintf(&buf, tt.s, tt.a...)
got := buf.String()
assert.IsType(t, "", got)
assert.Equal(t, tt.want, got)
})
}
@@ -366,10 +772,8 @@ func TestStringf(t *testing.T) {
func BenchmarkBytes(b *testing.B) {
for _, tt := range stringTestCases {
b.Run(tt.name, func(b *testing.B) {
input := []byte(tt.s)
for i := 0; i < b.N; i++ {
Bytes(input)
Bytes(tt.s)
}
})
}