Support gitignore highlighting
Makefile.am
| 11 | 11 | gitile/handler.scm \ | |
| 12 | 12 | gitile/pages.scm \ | |
| 13 | 13 | gitile/repo.scm \ | |
| 14 | - | gitile/highlight/css.scm | |
| 14 | + | gitile/highlight/utils.scm \ | |
| 15 | + | gitile/highlight/gitignore.scm | |
| 15 | 16 | ||
| 16 | 17 | clean-go: | |
| 17 | 18 | find . -name '*.go' -delete |
assets/css/highlight.css
| 26 | 26 | font-weight: bold; | |
| 27 | 27 | } | |
| 28 | 28 | ||
| 29 | + | /* language-specific */ | |
| 30 | + | ||
| 31 | + | /*** | |
| 32 | + | * SCHEME * | |
| 33 | + | * ***/ | |
| 34 | + | ||
| 29 | 35 | .language-scheme .syntax-special { | |
| 30 | 36 | color: var(--keyword); | |
| 31 | 37 | font-weight: bold; | |
… | |||
| 38 | 44 | .language-scheme .syntax-open, .language-scheme .syntax-close { | |
| 39 | 45 | color: var(--comment); | |
| 40 | 46 | } | |
| 47 | + | ||
| 48 | + | /*** | |
| 49 | + | * GITIGNORE * | |
| 50 | + | * ***/ | |
| 51 | + | .language-gitignore .syntax-special { | |
| 52 | + | color: var(--keyword); | |
| 53 | + | } | |
gitile/code.scm
| 20 | 20 | #:use-module (ice-9 match) | |
| 21 | 21 | #:use-module (syntax-highlight) | |
| 22 | 22 | #:use-module (syntax-highlight scheme) | |
| 23 | - | #:use-module (gitile highlight css) | |
| 23 | + | #:use-module (gitile highlight gitignore) | |
| 24 | + | #:use-module ((gitile highlight utils) #:prefix gitile:) | |
| 24 | 25 | #:export (display-code | |
| 25 | 26 | display-formatted-code)) | |
| 26 | 27 | ||
… | |||
| 28 | 29 | (let* ((extension (car (reverse (string-split (basename path) #\.)))) | |
| 29 | 30 | (language (match extension | |
| 30 | 31 | ("scm" "scheme") | |
| 31 | - | ("css" "css") | |
| 32 | + | ("gitignore" "gitignore") | |
| 32 | 33 | (_ "unknown")))) | |
| 33 | 34 | `(table (@ (class ,(string-append "file-content language-" language))) | |
| 34 | - | ,@(split-tr (highlights->sxml (highlight-code content language)))))) | |
| 35 | + | ,@(split-tr (gitile:highlights->sxml (highlight-code content language)))))) | |
| 35 | 36 | ||
| 36 | 37 | (define (display-formatted-code content language) | |
| 37 | - | (highlights->sxml (highlight-code content language))) | |
| 38 | + | (gitile:highlights->sxml (highlight-code content language))) | |
| 38 | 39 | ||
| 39 | 40 | (define (highlight-code content language) | |
| 40 | 41 | (match language | |
| 41 | 42 | ("scheme" (highlight lex-scheme content)) | |
| 42 | - | ("css" (highlight lex-css content)) | |
| 43 | + | ("gitignore" (highlight lex-gitignore content)) | |
| 43 | 44 | (_ (list content)))) | |
| 44 | 45 | ||
| 45 | 46 | (define (split-lines content) | |
| 46 | 47 | (let loop ((content content) (result '()) (line '())) | |
| 47 | - | (match content | |
| 48 | + | (match (pk 'split-lines-content content) | |
| 48 | 49 | ((? string? s) (string-split s #\newline)) | |
| 49 | 50 | (() (append result (list line))) | |
| 50 | 51 | (((? string? s) content ...) | |
… | |||
| 77 | 78 | '())))))))) | |
| 78 | 79 | ||
| 79 | 80 | (define (split-tr content) | |
| 81 | + | (pk 'split-tr content) | |
| 80 | 82 | (let loop ((result '()) (lines (split-lines content)) (line-num 1)) | |
| 81 | 83 | (match lines | |
| 82 | 84 | (() result) | |
gitile/highlight/gitignore.scm unknown status 1
| 1 | + | (define-module (gitile highlight gitignore) | |
| 2 | + | #:use-module (ice-9 match) | |
| 3 | + | #:use-module (srfi srfi-1) | |
| 4 | + | #:use-module (srfi srfi-11) | |
| 5 | + | #:use-module (srfi srfi-26) | |
| 6 | + | #:use-module (syntax-highlight lexers) | |
| 7 | + | #:use-module (gitile highlight utils) | |
| 8 | + | #:export (lex-gitignore)) | |
| 9 | + | ||
| 10 | + | (define lex-line | |
| 11 | + | (lex-consume-until | |
| 12 | + | (lex-string "\n") | |
| 13 | + | (lex-any | |
| 14 | + | (lex-tag 'special (apply lex-any (map lex-string '("*" "**" "?")))) | |
| 15 | + | (lex-tag 'range (lex-delimited "[" #:until "]")) | |
| 16 | + | (apply lex-any (map lex-string '("\\!" "\\*" "\\\\" "\\?"))) | |
| 17 | + | (lex-char-set (char-set-complement (char-set #\newline #\\ #\* #\?)))) | |
| 18 | + | #:tag 'line)) | |
| 19 | + | ||
| 20 | + | (define lex-gitignore | |
| 21 | + | (lex-consume | |
| 22 | + | (lex-any (lex-tag 'comment (lex-delimited "#" #:until "\n")) | |
| 23 | + | (lex-tag 'special (lex-string "!")) | |
| 24 | + | lex-line))) |
gitile/highlight/utils.scm unknown status 1
| 1 | + | (define-module (gitile highlight utils) | |
| 2 | + | #:use-module (ice-9 match) | |
| 3 | + | #:use-module (srfi srfi-1) | |
| 4 | + | #:use-module (srfi srfi-11) | |
| 5 | + | #:use-module (syntax-highlight lexers) | |
| 6 | + | #:export (highlights->sxml | |
| 7 | + | lex-consume-until)) | |
| 8 | + | ||
| 9 | + | (define (flatten-highlights highlights) | |
| 10 | + | (define (flatten-highlights-aux content tokens) | |
| 11 | + | (pk 'content content 'tokens tokens) | |
| 12 | + | (match content | |
| 13 | + | ((? string? s) (if (null? tokens) | |
| 14 | + | s | |
| 15 | + | `((,@tokens ,s)))) | |
| 16 | + | (((? symbol? token) content ...) | |
| 17 | + | (flatten-highlights-aux content (cons token tokens))) | |
| 18 | + | ((? list? content) | |
| 19 | + | (append-map (lambda (c) (flatten-highlights-aux c tokens)) content)))) | |
| 20 | + | ||
| 21 | + | (pk 'content highlights) | |
| 22 | + | (flatten-highlights-aux highlights '())) | |
| 23 | + | ||
| 24 | + | (define (highlights->sxml highlights) | |
| 25 | + | (define flat-highlights (flatten-highlights highlights)) | |
| 26 | + | ||
| 27 | + | (define (tag->class tag) | |
| 28 | + | (string-append "syntax-" (symbol->string tag))) | |
| 29 | + | ||
| 30 | + | (pk 'highlights flat-highlights) | |
| 31 | + | ||
| 32 | + | (map (match-lambda | |
| 33 | + | ((? string? str) str) | |
| 34 | + | ((content ...) | |
| 35 | + | (let loop ((tags '()) (text "") (content content)) | |
| 36 | + | (match content | |
| 37 | + | (() `(span (@ (class ,(string-join (map tag->class tags) " "))) ,text)) | |
| 38 | + | (((? symbol? tag) content ...) | |
| 39 | + | (loop (cons tag tags) text content)) | |
| 40 | + | (((? string? s) content ...) | |
| 41 | + | (loop tags (string-append text s) content)))))) | |
| 42 | + | flat-highlights)) | |
| 43 | + | ||
| 44 | + | (define* (lex-consume-until until lexer #:key (tag #f)) | |
| 45 | + | "Return a lexer that always succeeds with a list of as many consecutive | |
| 46 | + | successful applications of LEXER as possible, consuming the entire input text, | |
| 47 | + | or until a successful match of UNTIL, whichever comes first. Sections of text | |
| 48 | + | that could not be lexed are returned as plain strings." | |
| 49 | + | (define (substring* cursor start) | |
| 50 | + | (substring (cursor-text cursor) start (cursor-position cursor))) | |
| 51 | + | ||
| 52 | + | (define (consume-until tokens cursor) | |
| 53 | + | (if (cursor-end? cursor) | |
| 54 | + | (values tokens cursor) | |
| 55 | + | (let-values (((result remainder) (until tokens cursor))) | |
| 56 | + | (if result | |
| 57 | + | (values result remainder) | |
| 58 | + | (let-values (((result remainder) (lexer tokens cursor))) | |
| 59 | + | (if result | |
| 60 | + | (consume-until result remainder) | |
| 61 | + | (values (token-add tokens (cursor->string cursor)) | |
| 62 | + | (move-cursor-to-end cursor)))))))) | |
| 63 | + | ||
| 64 | + | (if tag | |
| 65 | + | (lambda (tokens cursor) | |
| 66 | + | (let-values (((result remainder) (consume-until empty-tokens cursor))) | |
| 67 | + | (values (pk (token-add tokens (list tag (tokens->list result)))) remainder))) | |
| 68 | + | consume-until)) |