codespell-project / codespell

check code for common misspellings
GNU General Public License v2.0
1.81k stars 465 forks source link

Still cannot specify custom + default dictionary in codespellrc file #3474

Closed oddhack closed 2 weeks ago

oddhack commented 2 weeks ago

I had thought this was addressed by #2767 / #2727 in codespell 2.3.0, but AFAICT this is still not supported. For example I can successfully do

codespell --builtin clear,rare -D - -D my-dictionary

with the desired behavior. But trying to replicate this in my codespellrc via

builtin = clear,rare
dictionary = -
dictionary = my-dictionary

gives a "ERROR: ill-formed config file: While reading from '/path/to/codespellrc' [line 6] option 'dictionary' in section 'codespell' already exists", while

builtin = clear,rare
dictionary = -,my-dictionary

gives a "error: argument -D/--dictionary: expected one argument" error.

Am I misunderstanding something about how this is supposed to work, such that there is now a way to specify both builtin and custom dictionaries? Or is there still more TBD in this area? @larsoner you apparently closed #2727 as completed, so if you can provide some insight, I'd appreciate it.

DimitriPapadopoulos commented 2 weeks ago

That's a niche case.

DimitriPapadopoulos commented 2 weeks ago

This works:

$ codespell -D /tmp/foo,/tmp/bar TEST.txt
$ 
$ codespell -D /tmp/foo,/tmp/bar,- TEST.txt
TEST.txt:1: aapply ==> apply
$ 

This doesn't work:

$ codespell -D -,/tmp/foo,/tmp/bar TEST.txt
usage: codespell [-h] [--version] [-d] [-c] [-w] [-D DICTIONARY] [--builtin BUILTIN-LIST] [--ignore-regex IGNORE_REGEX] [-I FILES]
                 [-L WORDS] [--uri-ignore-words-list WORDS] [-r REGEX] [--uri-regex URI_REGEX] [-s] [--count] [-S SKIP] [-x FILES]
                 [-i MODE] [-q LEVEL] [-e] [-f] [-H] [-A LINES] [-B LINES] [-C LINES] [--stdin-single-line] [--config CONFIG]
                 [--toml TOML]
                 [files ...]
codespell: error: argument -D/--dictionary: expected one argument
$ 

Please try:

dictionary = my-dictionary,-

instead of:

dictionary = -,my-dictionary
oddhack commented 2 weeks ago

Thanks. That does seem to work - so perhaps the description in the --help entry should be something more like this?

-D DICTIONARY-LIST, -dictionary DICTIONARY-LIST
comma-separated list of custom dictionary files that contain spelling corrections, and/or '-' to use the default or specified builtin dictionaries in addition to any custom files. If '-' is present, it must be the last entry in the list.

oddhack commented 2 weeks ago

Though maybe it just has to not be the first entry in the list? Not sure how the argument parser handles this but it seems likely to be picking up '-,filename' as an option even though it immediately follows -D which requires an argument.

DimitriPapadopoulos commented 2 weeks ago

Indeed, it shouldn't be the first entry. I think we abuse the argparse.ArgumentParser and feed it config files entries as if they were command line options, by merely adding the -- prefix: https://github.com/codespell-project/codespell/blob/73e3e28afd96b114961f26183739fa2dd71eb436/codespell_lib/_codespell.py#L643-L649

DimitriPapadopoulos commented 2 weeks ago

Fixing this might require considerable effort.

Documenting this bug as a feature feels awkward.

I don't know how to handle this.

oddhack commented 2 weeks ago

As J. Random User, I'd be happy to just have the restriction documented along the lines of my suggestion - no need to explain why the restriction is there or call it a bug, but letting people know not to do that would have avoided this issue to begin with :-) If the leading '-' restriction applies to other options as I expect it does, perhaps it could be lifted up to the beginning of the help entry. Happy to propose a doc PR if you are open to that.

DimitriPapadopoulos commented 2 weeks ago

The restriction is that the value of a config file entry cannot start with a - character. These config file entries won't work:

dictionary = -,foo,bar
ignore-words = -foo,bar
ignore-words = --foo,bar

As a workaround, use:

dictionary = foo,bar,-
ignore-words = bar,-foo
ignore-words = bar,--foo

The restriction does not need to be documented for command line options, as this is standard behaviour on the command line. It can be documented for config file entries, in section Using a config file.