-
-
Notifications
You must be signed in to change notification settings - Fork 261
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
Add Codeblock Syntax Highlighting using Pygments #1012
Conversation
@Rohitth007 This doesn't run for me - you don't seem to have added the dependency information in a commit? I could guess, but please add it as a separate commit for now based on what you have installed locally. |
@neiljp Strange, can I know what the error was because I haven't installed anything separately. |
2997db6
to
cdd0a40
Compare
Currently I have added the colors into the palette after the screen is initialized. I think it's better to do it inside |
I have added Pygments as a dependency into |
@zulipbot add "feedback wanted" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Rohitth007 This works much better for me now 👍
I can still observe some bugs, which might be clearer where they come from once you add some tests and if you can perhaps simplify the padding algorithm: (these are more/only visible somewhere after the latter 3 commits)
- See first line of last message by 'Mehdi Hamidi' in #test here>codeblock (user list is disrupted)
- See message by 'Vishwesh JainKuniya' in #test here>code on July 31 2017 (bottom line content is absent)
I think the first three commits are close to merging as they are, pending at least the following:
- given we're modifying the behavior for code, I'd like to see the soup2markup test updated for this
- using the pygments: namespace to avoid accidental style name conflicts
- improving the commit title/text to match the styles we have (eg. see the requirements lines we use for dependencies)
- clarifying what the 'old' vs 'new' messages categories are
- I'm not sure what we can do about inline code styles, but we likely want them to match in some way at least
max_line_len = len(max(code_text.split("\n"), key=lambda x: len(x))) | ||
|
||
line_len = 0 | ||
for code_element in code_soup.contents: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic here looks very complex, and I can't tell if it's doing the correct thing. Can you loop over lines instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@neiljp No that is not possible, we have to parse element wise. Sometimes that element can contain only one character only. I think if we split lines using code_text we would loose out on tag information(css class, element). I can write a docstring explaining the codeblock
format?
@neiljp Minor addition: Used Pygments style for inline code |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Rohitth007 I'm focusing on the first three first, since they should be able to be merged together first, possibly with the new last commit if we reorder them?
The tests are a good improvement, and also document what tags are doing (see minor inline comment).
My biggest concern for the first 3 (and maybe last one?) is the style behavior, including at different depths - both ensuring they're consistent with what we have now (monochrome; see inline comment) and have good contrast with the surrounding text (like now). Things like python, js or bash tagged code look colored great, but with no language tag it just looks like regular text, not a code block - and so it doesn't stand out from the surrounding text that well. I understand we expect to have theme-specific pygments styles, but we want it to keep working well close to how it is for now.
I'd also like to have a reference for that change in syntax (<code>
) in a comment - various parts of the community may know the origin of that if it's not obvious in discussions/logs.
In the next iteration, improving the commit title/text to match the styles we have will make it easier and quicker to merge commits (I think I mentioned that above)
tests/ui/test_ui_tools.py
Outdated
"<code><span>def</span> <span>func</span><span>():</span>\n" | ||
' <span class="pg">print</span><span>()</span>\n' | ||
"\n" | ||
"<span>class</span> <span>New</span><span>:</span>\n" | ||
' <span>name</span> <span>=</span> <span>"name"</span>\n' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only one class here looks odd - there are many others in code from the server?
For the second test you could have a smaller code example, if you're concerned about space.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to test multiple empty lines and spaces, hence the longer tests. I don't think it matters what "text/syntax" is used for testing here as pygments is not directly involved.
tests/ui/test_ui_tools.py
Outdated
[ | ||
("pygments:w", "This is a\n Plain\n\n Codeblock\n"), | ||
], | ||
id="codehilite-plain-codeblock", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be useful to clarify "plain" - no language?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have used plain-text-codeblock
instead
01ea552
to
b1203ea
Compare
6575c89
to
e65b748
Compare
This commit adds Pygments dependency (>=2.81) to `setup.py`. NOTE: Pygments is also a dependency for Pudb.
This commit uses Pygments internal dictionaries and PygmentsStyles to add it into the palette right after theme generation. For this a META dict is defined in each theme file which contains syntax highlighting styles and overrides. The conversion to urwid compatible theme format is done inside `add_pygments_style` and called in `generate_theme`. The function does the following: * Checks if any overrides are necessary. * Checks if any parent pygment style can be used i it is not defined * Adds new_style to urwid_theme. Tests added. * REQUIRED_META added to test completeness.
This commit creates a custom 16 color syntax theme for use in all 16 color depth ZT themes. Tests updated.
This commit extracts the `code_soup` to be further parsed for css styles. Each `codehilite` associated tag has a `pre` tag wrapped around a `code` tag which contains `span` tags and NavigableStrings. In some old messages, the `code` tag doesn't exist which is also dealt with. Basic syntax highlighting functionality was implemented in soup2markup by extracting the `css_style` of each `span` tag in the soup and using it as urwid style attributes. The remaining NavigableStrings are given a style attribute of `w` which is the whitespace css class in Pygments. Tests amended.
d9d6855
to
6ae3ac3
Compare
This commit moves the previous code into `parse_codeblock`, a static method which creates a visual "box" by: * Finding the longest line using `code_soup.text`. * Appending `span` text into markup * Adding the NavigableStrings not contributing to line breaks into markup. * Adding `right_padding` to the end of each line. * Making sure multiple empty lines are padded using `padded_line`. * Adding `code_indent` part of the NavigableString to markup at the start of a new line. The NavigableString is added in parts and not all at once because though it would produce the same output, it would later help while implementing `hl_lines` preventing the case where half the previous line is highlighted along with the line expected. Tests amended.
This commit sets a limit to how much padding is to be added. Many a times most of the code has smaller lines and there is one line which is very long which causes all the lines to wrap and this makes the "box" look very messy. To avoid this a `MAX_NO_WRAP_WIDTH` constant of 70 is used which is a reasonable limit for in a full screen no autohide mode.
This comment introduces the same style used for plain codeblocks for inline code. Tests amended.
Heads up @Rohitth007, we just merged some commits that conflict with the changes your made in this pull request! You can review this repository's recent commits to see where the conflicts occur. Please rebase your feature branch against the |
Heads up @Rohitth007, we just merged some commits that conflict with the changes your made in this pull request! You can review this repository's recent commits to see where the conflicts occur. Please rebase your feature branch against the |
@Rohitth007 I'm thinking of close this, since some of these commits were merged already. I'd suggest you open a new PR with the remaining work after fetching and rebasing, so we can focus on those. That said, I know it wasn't clear what to do regarding long lines and we ended up with various options based on spaces, which wraps badly. Do you think a widget-based approach might work better? |
This comment introduces the same style used for plain codeblocks for inline code. Test amended. Adapted from the last commit of zulip#1012 by neiljp.
This ensures similar rendering of the two code formats, by using the style used for plain codeblocks for inline code: "pygments:w". Test amended. Adapted from the last commit of zulip#1012 by neiljp.
This ensures similar rendering of the two code formats, by using the style used for plain codeblocks for inline code: "pygments:w". Test amended. Adapted from the last commit of #1012 by neiljp.
@Rohitth007 Thanks for all the work on the syntax highlighting! 👍 I've just merged #1346 with a version of the last commit from here, which sets the inline style to match codeblocks, though I adjusted the existing theme style name rather than removing it, since we still use it elsewhere. We discussed flattening the edges of the code blocks in a separate PR, but I don't believe anything came of that, so I've opened #1347 for that remaining element. That points back here for reference, so I'm going to close this now, since I recall that was the remaining element we hadn't merged. |
This PR implements syntax highlighting for markdown code blocks by creating a padded "box" which would
visually separate as code. Currently, only looks good in dark theme.
Commit 1: themes: codehilite: Adding Pygments style to the palette.
Material Style and adds it into the palette after the Screen is
initialized. This is done inside
add_codehilite_style
and calledin
Controller.__init__
.Commit 2: boxes: codehilite: Implement syntax highlighting functionality.
soup2markup by extracting the
css_style
of eachspan
tag in thesoup and using it as urwid style attributes. The remaining
NavigableStrings are given a style attribute of
w
which is thewhitespace css class in Pygments.
Commit 3: boxes: codehilite: Create a visual "box" by padding whitespaces.
parse_codeblock
, a staticmethod which creates a visual "box" by:
code_soup.text
.span
text into markupcode_indent
part of the NavigableString to markup.right_padding
to each line.padded_line
.breaks into markup.
though it would produce the same output, it would later help while
implementing
hl_lines
preventing the case where half the previousline is highlighted along with the line expected.
Commit 4: boxes: codehilite: Implement padding for Plain Codeblocks.
the usual multiple
span
's in apre
tag package. The whole codeis a NavigableString which does not start with
\n
.accordingly.
Commit 5: boxes: codehilite: Restrict padding to avoid wrapping.
times most of the code has smaller lines and there is one line which
is very long which causes all the lines to wrap and this makes the
"box" look very messy. To avoid this a
MAX_NO_WRAP_WIDTH
constantof 80 is used which is a reasonable limit for in a full screen
no autohide mode.