Skip to content
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 an ability to highlight lines for Scribble's Pygments #238

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
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
39 changes: 30 additions & 9 deletions frog/enhance-body.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,28 @@
@racket[find-executable-path], so the default @racket["python"]
will work if the version of Python that Pygments wants is on the
path.}
(define (highlight brush texts hl-lines)
(match brush
[(pregexp "\\s*brush:\\s*(.+?)\\s*$" (list _ lang))
`(div ([class ,(str "brush: " lang)])
,@(pygmentize (apply string-append texts) lang
#:python-executable python-executable
#:line-numbers? line-numbers?
#:css-class css-class
#:hl-lines hl-lines))]
[_ `(pre ,@texts)]))

(let recur ([xs x-expressions])
(for/list ([x xs])
(match x
[(or `(pre ([class ,brush]) (code () ,(? string? texts) ...))
`(pre ([class ,brush]) ,(? string? texts) ...))
(match brush
[(pregexp "\\s*brush:\\s*(.+?)\\s*$" (list _ lang))
`(div ([class ,(str "brush: " lang)])
,@(pygmentize (apply string-append texts) lang
#:python-executable python-executable
#:line-numbers? line-numbers?
#:css-class css-class))]
[_ `(pre ,@texts)])]
(highlight brush texts '())]
[(or `(pre ([class ,brush] [data-hl-lines ,hl-lines])
(code () ,(? string? texts) ...))
`(pre ([class ,brush] [data-hl-lines ,hl-lines])
,(? string? texts) ...))
(highlight brush texts (map string->number (string-split hl-lines " ")))]
;; Check child elements, too. For example as in issue #217
;; could be (ol () (li () (pre () ___))).
[(list* (? symbol? tag) (? list? attributes) elements)
Expand Down Expand Up @@ -126,7 +135,19 @@
[(`((pre . ,_)
(div . ,_)
,_ ... ;varies: line numbers?
(div ([class "brush: racket"]) . ,_))
(div ([class "brush: racket"]) . ,_)
,_ ...)
`(span ([class ,(and c (not "c1") (not "hll"))]) . ,xs))
(if code?
`(span ([class ,c]) ,@(->racket-doc-links xs))
x)]
;; This is the case where the line is highlighted.
[(`((span ([class "hll"]) . ,_)
(pre . ,_)
(div . ,_)
,_ ... ;varies: line numbers?
(div ([class "brush: racket"]) . ,_)
,_ ...)
`(span ([class ,(and c (not "c1"))]) . ,xs))
(if code?
`(span ([class ,c]) ,@(->racket-doc-links xs))
Expand Down
11 changes: 8 additions & 3 deletions frog/frog.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -413,19 +413,24 @@ Scribble non-post page} for more information.

@defmodule[frog/scribble]

@defproc[(pygment-code [#:lang lang string?][str string?] ...) paragraph?]{
@defproc[(pygment-code [#:lang lang string?][#:hl-lines hl-lines list? '()][str string?] ...) paragraph?]{
In Scribble source files of course you can use @racket[codeblock],
@racket[racketblock], and friends to write code blocks for languages
that have DrRacket style syntax-coloring parsers.

For other languages, you can emit a @tt{<pre>} block with a language
tag (as happens with @secref["markdown-code-blocks"]) so that it can
be highlighted by Pygments.
be highlighted by Pygments. You can also additionally supply lines to be
highlighted via @racket[#:hl-lines].

Example usage:
@pre|{
@(require frog/scribble)
@pygment-code[#:lang "js"]{function foo() {return 1;}}
@pygment-code[#:lang "js" #:hl-lines '(1 2)]{
function foo() {
return 1;
}
}
}|
}

Expand Down
15 changes: 11 additions & 4 deletions frog/private/enhance-body/syntax-highlight/pipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# continuously. Input format is:
#
# <lexer-name>
# <list-of-highlighted-lines>
# <code>
# ...
# __END__
Expand All @@ -28,12 +29,9 @@
parser.add_option('--cssclass', default="source", dest="cssclass")
(options, _) = parser.parse_args()

formatter = HtmlFormatter(linenos=options.linenos,
cssclass=options.cssclass,
encoding="utf-8")

lexer = ""
code = ""
lines_to_highlight = ""
py_version = sys.version_info.major
sys.stdout.write("ready\n")
sys.stdout.flush()
Expand All @@ -47,6 +45,10 @@
break
elif line == '__END__':
# Lex input finished. Lex it.
formatter = HtmlFormatter(linenos=options.linenos,
cssclass=options.cssclass,
encoding="utf-8",
hl_lines=lines_to_highlight)
if py_version >= 3:
sys.stdout.write(highlight(code, lexer, formatter).decode("utf-8"))
else:
Expand All @@ -55,12 +57,17 @@
sys.stdout.flush()
lexer = ""
code = ""
lines_to_highlight = ""
elif lexer == "":
# Starting another lex. First line is the lexer name.
try:
lexer = get_lexer_by_name(line, encoding="guess")
except ClassNotFound:
lexer = get_lexer_by_name("text", encoding="guess")
elif lines_to_highlight == "":
# Starting another lex. Second line is list of lines to highlight,
# formatted as string of whitespace-separated integers
lines_to_highlight = [int(str) for str in line.split()]
else:
# Accumulate more code
# Use `line_raw`: Do want trailing space, \n, \r
Expand Down
5 changes: 4 additions & 1 deletion frog/private/enhance-body/syntax-highlight/pygments.rkt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#lang racket/base

(require racket/format
racket/string
racket/function
racket/match
racket/port
Expand Down Expand Up @@ -66,13 +67,15 @@
(define (pygmentize code lang
#:python-executable python-executable
#:line-numbers? line-numbers?
#:css-class css-class)
#:css-class css-class
#:hl-lines [hl-lines '()])
(define (default code)
`((pre () (code () ,code))))
(unless (running?)
(start python-executable line-numbers? css-class))
(cond [(running?)
(displayln lang pyg-out)
(displayln (string-join (map number->string hl-lines) " ") pyg-out)
(displayln code pyg-out)
(displayln "__END__" pyg-out)
(let loop ([s ""])
Expand Down
15 changes: 10 additions & 5 deletions frog/scribble.rkt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#lang racket/base

(require (only-in scribble/core style)
(require racket/string
(only-in scribble/core style)
(only-in scribble/manual para)
(only-in scribble/html-properties attributes alt-tag)
(only-in scribble/base literal))
Expand All @@ -17,8 +18,12 @@
;;
;; @pygment-code[#:lang "js"]{function foo() {return 1;}}
;;
(define (pygment-code #:lang lang . xs)
(para #:style (style "brush:"
(list (attributes `([class . ,lang]))
(alt-tag "pre")))
(define (pygment-code #:lang lang #:hl-lines [hl-lines '()] . xs)
(para #:style
(style "brush:"
(list (attributes
`([class . ,lang]
[data-hl-lines . ,(string-join (map number->string hl-lines)
" ")]))
(alt-tag "pre")))
(apply literal xs)))