rdbende/chlorophyll

Use of configure results in error

strangefreeworld opened this issue · 15 comments

When I do something like:

def open_file(filename): lexer = pygments.lexers.get_lexer_for_filename(filename) code_view.configure(lexer=lexer)
I get the following error:

File "/home/user/.cache/pypoetry/virtualenvs/qdnote-xQFX2N3W-py3.10/lib/python3.10/site-packages/chlorophyll/codeview.py", line 217, in configure
self._set_lexer(lexer)
File "/home/user/.cache/pypoetry/virtualenvs/qdnote-xQFX2N3W-py3.10/lib/python3.10/site-packages/chlorophyll/codeview.py", line 204, in _set_lexer
self.highlight_all()
File "/home/user/.cache/pypoetry/virtualenvs/qdnote-xQFX2N3W-py3.10/lib/python3.10/site-packages/chlorophyll/codeview.py", line 165, in highlight_all
for token, text in lex(lines, self._lexer()):
TypeError: 'PythonLexer' object is not callable

Have you tried using codeview. _set_lexer(lexer)?

Sorry, the type annotation for lexer is wrong. It expects a lexer class, not an actual instance.

Have you tried using codeview. _set_lexer(lexer)?

Btw, don't use _set_lexer it's not a public method.

Yes I figured out it is looking for a class, not an instance. I can work around that; if possible, I would suggest you document that somewhere. Given how I am trying to use the class, it would be nice if there was an interface that could give me the class based on the file extension, something similar to pygments' get_lexer_for_filename.

A suggestion to @Moosems (I apologize if this is harsh): if you had looked at the actual stack trace I had provided, you would see that _set_lexer is being called.

If I find a solution I like I may create a PR.

Can you provide a minimum reproducible example? I have. a program that utilizes chlorophyll and changes the lexer and have never encountered this issue.

Pass a lexer that you get from the results of https://pygments.org/docs/api/#pygments.lexers.get_lexer_for_filename. It passes an instantiated object rather than a class instance. If you do that, you get error that I mentioned earlier in my initial post (which by the way calls _set_lexer). I posted a simple code sample in my initial report, you should be able to create a minimum example from that (you just need a codeview instance).

Actually, in a sane world, that argument should accept a lexer instance.

I agree with this 100%.

Ah that's why. It requires the class itself. There are ways to get them from an instantiated object.

Obviously you could use type(lexer_instance), but you shouldn't have to.

Quick PR that runs lexer = type(lexer) in set lexer?

No. Rather a quick PR that runs

self._lexer = lexer() if isclass(lexer) else lexer

And then remove then parens from the highlight methods from the line containing lex(..., self._lexer())

Also much faster to use one lexer than instantiate one for every highlight.