Skip to content
Open
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
20 changes: 20 additions & 0 deletions codespell_lib/_codespell.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,17 @@ def convert_arg_line_to_args(self, arg_line: str) -> list[str]:
"by codespell. Words are case sensitive based on "
"how they are written in the dictionary file.",
)
parser.add_argument(
"--min-word-length",
action="store",
type=int,
default=0,
metavar="LENGTH",
help="only check words at least LENGTH characters long, "
"e.g., use 4 to not check words of 3 or fewer characters "
"(such as short variable names). "
"The default is %(default)s (check all words).",
)
parser.add_argument(
"--uri-ignore-words-list",
action="append",
Expand Down Expand Up @@ -1433,6 +1444,15 @@ def main(*args: str) -> int:
misspellings: dict[str, Misspelling] = {}
for dictionary in use_dictionaries:
build_dict(dictionary, misspellings, ignore_words)
if options.min_word_length > 0:
# Words shorter than the requested length can never match a
# misspelling, so dropping them from the dictionary up front ignores
# them everywhere (file contents and --check-filenames alike).
misspellings = {
key: value
for key, value in misspellings.items()
if len(key) >= options.min_word_length
}
colors = TermColors()
if not options.colors:
colors.disable()
Expand Down
24 changes: 24 additions & 0 deletions codespell_lib/tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,30 @@ def test_ignore_word_list(
assert cs.main("-Labandonned,someword", "-Labilty", tmp_path) == 1


def test_min_word_length(
tmp_path: Path,
capsys: pytest.CaptureFixture[str],
) -> None:
"""Test that --min-word-length ignores short words."""
bad_name = tmp_path / "bad.txt"
bad_name.write_text("nwe abilty abandonned\n")
assert cs.main(bad_name) == 3
assert cs.main("--min-word-length", 0, bad_name) == 3, "0 checks all words"
assert cs.main("--min-word-length", 3, bad_name) == 3, "'nwe' is 3 chars long"
assert cs.main("--min-word-length", 4, bad_name) == 2
assert cs.main("--min-word-length", 7, bad_name) == 1
assert cs.main("--min-word-length", 11, bad_name) == 0
# case-insensitive: the dictionary key length is what matters
bad_name.write_text("NWE\n")
assert cs.main(bad_name) == 1
assert cs.main("--min-word-length", 4, bad_name) == 0
# also applies to --check-filenames
fname = tmp_path / "nwe.txt"
fname.write_text("good contents\n")
assert cs.main("-f", fname) == 1
assert cs.main("-f", "--min-word-length", 4, fname) == 0


@pytest.mark.parametrize(
("content", "expected_error_count"),
[
Expand Down