-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
enable syntax highlighting for inline code #17585
Conversation
IMO that's the only controversial thing in this PR due to the other implications you listed. In subsequent PR we can revisit that point, so that it doesn't block the rest of this PR
{.emit: """
#include <stdio.h>
""".lang(cpp).}
const s = """
import os
""".lang(py)
writeFile("foo.py", s)
# or even reusing apostrophe syntax, eg:
const s = """
import os
"""'py where |
@timotheecour
|
then how about this for single backtick without explicit role:
that fits well with your 95% vs 50% stats, as well as with rst spec (ie honors |
I think we will have another spell in every rst file instead:
Github does not highlight it but it's still rendered as code: https://github.com/a-mr/Nim/blob/test-branch/doc/tut2.rst (of course, currently Nim would say "Error: invalid directive: 'role'") |
can these lines be replace by a single include instead?
and then we can add to rstcommon.rst whatever's in common, eg:
(and perhaps more, eg related to a common index, or C language highlighting, etc) |
Tried it. (#4864 seems unrelated) |
ok how about:
which should at least display as code in github, and then still allows factoring all common definitions in 1 place (including overriding |
implementation
Agreed. Added missing parts for |
lib/packages/docutils/rst.nim
Outdated
@@ -514,10 +525,17 @@ proc defaultFindFile*(filename: string): string = | |||
if fileExists(filename): result = filename | |||
else: result = "" | |||
|
|||
proc defaultRoleKind(options: RstParseOptions): RstNodeKind = |
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.
instead of adding defaultRoleKind
, you could infer it from currRole, eg:
p.s.currRoleKind = defaultRoleKind(p.s.options)
p.s.currRole = defaultRole(p.s.options)
=>
p.s.currRole = defaultRole(p.s.options)
p.s.currRoleKind = whichRole(p, p.s.currRole)
(a bit more DRY)
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.
done.
proc defaultRoleKind(options: RstParseOptions): RstNodeKind = | ||
if roNimFile in options: rnInlineCode else: rnInlineLiteral | ||
proc defaultRole(options: RstParseOptions): string = | ||
if roNimFile in options: "nim" else: "literal" |
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.
add
type BuiltinRoles = enum
brUnknown = "unknown"
brNim = "nim"
brLiteral = "literal"
brCode = "code"
... # doesn't need to be a complete list
and then use it everytime you're using one of those builtin roles, it's more typesafe eg:
if roNimFile in options: $brNim else: $brLiteral
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.
too little profit for a new type. Most roles are met only once and immediately converted to RstNodeKind. The only exception is "nim" and "literal", which occur twice, but both occurrences are within a few lines.
lib/packages/docutils/rst.nim
Outdated
@@ -1018,15 +1036,43 @@ proc fixupEmbeddedRef(n, a, b: PRstNode) = | |||
for i in countup(0, sep - incr): a.add(n.sons[i]) | |||
for i in countup(sep + 1, n.len - 2): b.add(n.sons[i]) | |||
|
|||
proc whichRole(sym: string): RstNodeKind = | |||
case sym | |||
const supportedLanguages = ["nim", "yaml", "python", "java", "c", |
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.
is that supposed to stay in sync with
const
sourceLanguageToStr*: array[SourceLanguage, string] = ["none",
"Nim", "C++", "C#", "C", "Java", "Yaml", "Python"]
from lib/packages/docutils/highlite.nim? if so, refactor (DRY)
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.
ideally, yes, but mirror should be maintained anyway, because c#
role would not be allowed according to RST spec:
A role name is a single word consisting of alphanumerics plus isolated internal hyphens, underscores, plus signs, colons, and periods; no whitespace or other characters are allowed.
result = newRstNode(rnInlineCode) | ||
var args = newRstNode(rnDirArg) | ||
var lang = language | ||
if language == "cpp": lang = "c++" |
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.
something is inconsistent:
.. code-block:: cpp
#include <stdio.h>
.. code-block:: c++
#include <stdio.h>
`#include <stdio.h>`:cpp:
`#include <stdio.h>`:c++:
=> depending on block vs inline, the syntax that works is c++ vs cpp
we should have one that works in all contexts, and recommend it (including in example from eariler).
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 fact that :c++:
is not parsed is another bug in our parser. Added to the list of minor bugs.
The proper fix (with code reusing) is not trivial, it's better to handle in another PR.
lib/packages/docutils/rst.nim
Outdated
@@ -1052,14 +1098,23 @@ proc parsePostfix(p: var RstParser, n: PRstNode): PRstNode = | |||
result = newRstNode(newKind, newSons) | |||
elif match(p, p.idx, ":w:"): | |||
# a role: | |||
newKind = whichRole(nextTok(p).symbol) | |||
let roleName = nextTok(p).symbol | |||
newKind = whichRole(p, roleName) | |||
if newKind == rnGeneralRole: |
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.
case newKind
of ...
of ...
else: ...
dispA(d.target, result, blockStart, | ||
"\\begin{rstpre}\n" & n.anchor.idS & "\n", []) | ||
else: # rnInlineCode | ||
blockStart = "<tt class=\"docutils literal\"><span class=\"pre\">" |
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.
prefer """ ... """ to make it easier to copy paste
@@ -201,14 +206,14 @@ not in table""" | |||
`|` outside a table cell should render as `\|` | |||
consistently with markdown, see https://stackoverflow.com/a/66557930/1426932 | |||
]# | |||
doAssert output1 == """ | |||
check(output1 == """ |
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.
how about import std/strformat and using &"". {...}..""" to avoid breaking the string?
ditto in other examples below
IMO, resulting code is less noisy, easier to read/edit
check """`foo\`bar`""".toHtml == """<tt class="docutils literal"><span class="pre">foo`bar</span></tt>""" | ||
check """`\`bar`""".toHtml == """<tt class="docutils literal"><span class="pre">`bar</span></tt>""" | ||
check """`a\b\x\\ar`""".toHtml == """<tt class="docutils literal"><span class="pre">a\b\x\\ar</span></tt>""" | ||
check("""`foo.bar`""".toHtml == |
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.
these get more and more complicated to read/write/maintain, we should really look into timotheecour#676 at some point
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.
LGTM, remaining comments can be addressed preferably before merging but in followup PR is ok too
Co-authored-by: Timothee Cour <[email protected]>
Co-authored-by: Timothee Cour <[email protected]>
… enable-inline-highlighting
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.
still LGTM , and previous LGTM comment still applies: remaining comments can be addressed either in this PR or in followup PR
Add highlighting of text in single backticks as Nim code, just like it works for code-blocks.
An example from Nim Manual:
An artificial example:
the corresponding RST text:
It also highlights blindly non-code like this:
To avoid this spurious highlighting the following rule is added to
contributing.rst
for using single and double backticks:use single backticks for fragments of code in Nim and other
programming languages, including identifiers
prefer double backticks otherwise:
"
and"
and notrelated to code, e.g. text of compiler messages
\
(otherwise a combination of\
and a final ` would get escaped)Ref. nim-lang/RFCs#355 for discussion on syntax.
Later it will be possible to switch default role (programming language or just literal), ref bug #17340.
cc @narimiran @timotheecour