diff --git a/docs/tool-guide.md b/docs/tool-guide.md index ed54a58..e752d27 100644 --- a/docs/tool-guide.md +++ b/docs/tool-guide.md @@ -7,7 +7,10 @@ MCP imports. Examples below show Python arguments; MCP uses the same parameter n `analyze_text("Hi hi!")` returns `characters=6`, `words=2`, `lines=1`, `sentences=1`, and `frequent_words=[{"word": "hi", "count": 2}]`. -Characters include whitespace. Words are Unicode letter/digit sequences with +Characters include +whitespace; `characters_without_whitespace` counts every character for which +`str.isspace()` is false, so punctuation and digits still count. Words are Unicode letter/digit +sequences with optional internal apostrophes; underscores separate words. Frequency is case-insensitive, with ties ordered by first appearance. Lines follow `str.splitlines()`: empty input has zero lines and a final newline does not add an extra line. diff --git a/src/mcp_tools_lab/tools/text.py b/src/mcp_tools_lab/tools/text.py index f02fc71..0819ba4 100644 --- a/src/mcp_tools_lab/tools/text.py +++ b/src/mcp_tools_lab/tools/text.py @@ -9,11 +9,16 @@ def analyze_text(text: str) -> dict: Words are letter/digit sequences (apostrophes within words are kept). Sentences are nonempty pieces separated by '.', '!', or '?'. + Characters exclude anything str.isspace() recognizes when counting + characters_without_whitespace. This is a simple heuristic, not linguistic analysis. """ words = re.findall(r"[^\W_]+(?:['’][^\W_]+)*", text.lower()) return { "characters": len(text), + "characters_without_whitespace": sum( + not character.isspace() for character in text + ), "words": len(words), "lines": len(text.splitlines()), "sentences": sum(bool(part.strip()) for part in re.split(r"[.!?]+", text)), diff --git a/tests/test_text.py b/tests/test_text.py index c5ced02..2620bb3 100644 --- a/tests/test_text.py +++ b/tests/test_text.py @@ -2,7 +2,9 @@ def test_empty_text(): - assert analyze_text("") == {"characters": 0, "words": 0, "lines": 0, + assert analyze_text("") == {"characters": 0, + "characters_without_whitespace": 0, + "words": 0, "lines": 0, "sentences": 0, "frequent_words": []} @@ -18,3 +20,22 @@ def test_unicode_and_trailing_newline(): result = analyze_text("café café\n") assert result["words"] == 2 assert result["lines"] == 1 + + +def test_characters_without_whitespace(): + result = analyze_text("Hi there!\n") + assert result["characters"] == 10 + assert result["characters_without_whitespace"] == 8 + + +def test_characters_without_whitespace_keeps_punctuation_and_digits(): + result = analyze_text("a, 1\tb") + assert result["characters"] == 6 + assert result["characters_without_whitespace"] == 4 + + +def test_characters_without_whitespace_whitespace_only(): + result = analyze_text(" \t\r\n\u00a0") + assert result["characters"] == 5 + assert result["characters_without_whitespace"] == 0 + assert result["words"] == 0