Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New util method to normalize content newlines for use in LSP #234

Merged
merged 1 commit into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions ufmt/lsp.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
UsortConfig,
UsortConfigFactory,
)
from .util import make_black_config
from .util import make_black_config, normalize_content, normalize_result

ServerType = Literal["stdin", "tcp", "ws"]

Expand Down Expand Up @@ -111,7 +111,7 @@ def lsp_format_document(

# XXX: we're assuming everything is UTF-8 because LSP doesn't track encodings...
encoding: Encoding = "utf-8"
content = document.source.encode(encoding)
content, newline = normalize_content(document.source.encode(encoding))

result = _wrap_ufmt_bytes(
path,
Expand All @@ -137,7 +137,7 @@ def lsp_format_document(
Position(0, 0),
Position(len(document.lines), 0),
),
result.after.decode(encoding),
normalize_result(result.after, newline).decode(encoding),
),
]

Expand Down
30 changes: 30 additions & 0 deletions ufmt/tests/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,36 @@ def test_black_config(self) -> None:
with self.subTest("line_length"):
self.assertEqual(mode.line_length, 87)

def test_normalize_content(self) -> None:
cases = (
(b"hello world", None, (b"hello world", b"\n")),
(b"hello\nworld\n", None, (b"hello\nworld\n", b"\n")),
(b"hello\r\nworld\r\n", None, (b"hello\nworld\n", b"\r\n")),
(b"hello world", b"\n", (b"hello world", b"\n")),
(b"hello\nworld\n", b"\n", (b"hello\nworld\n", b"\n")),
(b"hello\r\nworld\r\n", b"\n", (b"hello\r\nworld\r\n", b"\n")),
(b"hello world", b"\r\n", (b"hello world", b"\r\n")),
(b"hello\nworld\n", b"\r\n", (b"hello\nworld\n", b"\r\n")),
(b"hello\r\nworld\r\n", b"\r\n", (b"hello\nworld\n", b"\r\n")),
)
for idx, (content, newline, expected) in enumerate(cases):
with self.subTest(idx):
self.assertEqual(
expected, ufmt.util.normalize_content(content, newline)
)

def test_normalize_result(self) -> None:
cases = (
(b"hello world", b"\n", b"hello world"),
(b"hello\nworld\n", b"\n", b"hello\nworld\n"),
(b"hello\r\nworld\r\n", b"\n", b"hello\r\nworld\r\n"),
(b"hello world", b"\r\n", b"hello world"),
(b"hello\nworld\n", b"\r\n", b"hello\r\nworld\r\n"),
)
for idx, (content, newline, expected) in enumerate(cases):
with self.subTest(idx):
self.assertEqual(expected, ufmt.util.normalize_result(content, newline))

def test_read_file(self) -> None:
with TemporaryDirectory() as td:
tdp = Path(td).resolve()
Expand Down
19 changes: 17 additions & 2 deletions ufmt/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import os
import tokenize
from pathlib import Path
from typing import Tuple
from typing import Optional, Tuple

from black.files import find_pyproject_toml, parse_pyproject_toml
from black.mode import TargetVersion
Expand Down Expand Up @@ -34,6 +34,21 @@ def make_black_config(path: Path) -> BlackConfig:
return BlackConfig(**config)


def normalize_content(
content: FileContent, newline: Optional[Newline] = None
) -> Tuple[FileContent, Newline]:
"""
Detect bytes content line ending style and convert to UNIX style.

No-op if ``newline`` is detected or given as ``b"\\n"``.
"""
if newline is None:
newline = b"\r\n" if content.find(b"\r\n", 0, 1000) > -1 else b"\n"
if newline != b"\n":
content = content.replace(newline, b"\n")
return content, newline


def normalize_result(content: FileContent, newline: Newline) -> FileContent:
"""
Convert bytes content with UNIX style line endings to the given style.
Expand Down Expand Up @@ -64,7 +79,7 @@ def read_file(path: Path) -> Tuple[FileContent, Encoding, Newline]:

buf.seek(0)
content = buf.read()
content = content.replace(newline, b"\n")
content, newline = normalize_content(content, newline)
return content, encoding, newline


Expand Down
Loading