diff options
Diffstat (limited to 'external')
-rwxr-xr-x | external/autopygmentize | 145 | ||||
-rwxr-xr-x | external/lasso-builtins-generator-9.lasso | 162 | ||||
-rw-r--r-- | external/lilypond-builtins-generator.ly | 391 | ||||
-rw-r--r-- | external/markdown-processor.py | 66 | ||||
-rw-r--r-- | external/moin-parser.py | 111 | ||||
-rw-r--r-- | external/pygments.bashcomp | 38 | ||||
-rw-r--r-- | external/rst-directive.py | 81 | ||||
-rw-r--r-- | external/scheme-builtins-generator.scm | 116 |
8 files changed, 1110 insertions, 0 deletions
diff --git a/external/autopygmentize b/external/autopygmentize new file mode 100755 index 0000000..85d2366 --- /dev/null +++ b/external/autopygmentize @@ -0,0 +1,145 @@ +#!/bin/bash +# Best effort auto-pygmentization with transparent decompression +# by Reuben Thomas 2008-2022 +# This program is in the public domain. + +# Strategy: first see if pygmentize can find a lexer; if not, ask file; if that finds nothing, fail +# Set the environment variable PYGMENTIZE_OPTS or pass options before the file path to configure pygments. + +# This program can be used as a .lessfilter for the less pager to auto-color less's output + +file="${!#}" # last argument +options=${@:1:$(($#-1))} # handle others args as options to pass to pygmentize + +file_common_opts="--brief --dereference" + +case $(file --mime-type --uncompress $file_common_opts "$file") in + application/xml|image/svg+xml) lexer=xml;; + application/javascript) lexer=javascript;; + application/json) lexer=json;; + text/html) lexer=html;; + text/troff) lexer=nroff;; + text/x-asm) lexer=nasm;; + text/x-awk) lexer=awk;; + text/x-c) lexer=c;; + text/x-c++) lexer=cpp;; + text/x-clojure) lexer=clojure;; + text/x-crystal) lexer=crystal;; + text/x-diff) lexer=diff;; + text/x-execline) lexer=execline;; + text/x-forth) lexer=forth;; + text/x-fortran) lexer=fortran;; + text/x-gawk) lexer=gawk;; + text/x-java) lexer=java;; + text/x-lisp) lexer=common-lisp;; + text/x-lua|text/x-luatex) lexer=lua;; + text/x-makefile) lexer=make;; + text/x-msdos-batch) lexer=bat;; + text/x-nawk) lexer=nawk;; + text/x-objective-c) lexer=objective-c;; + text/x-pascal) lexer=pascal;; + text/x-perl) lexer=perl;; + text/x-php) lexer=php;; + text/x-po) lexer=po;; + text/x-python) lexer=python;; + text/x-ruby) lexer=ruby;; + text/x-script.python) lexer=python;; + text/x-shellscript) lexer=sh;; + text/x-tcl) lexer=tcl;; + text/x-tex|text/x-texinfo) lexer=latex;; # FIXME: texinfo really needs its own lexer + text/xml) lexer=xml;; + text/vnd.graphviz) lexer=graphviz;; + + # Types that file outputs which pygmentize didn't support as of file 5.41, pygments 2.11.2 + # text/binary + # text/calendar + # text/PGP + # text/prs.lines.tag + # text/rtf + # text/spreadsheet + # text/texmacs + # text/vcard + # text/vnd.sosi + # text/x-Algol68 + # text/x-bcpl + # text/x-dmtf-mif + # text/x-gimp-curve + # text/x-gimp-ggr + # text/x-gimp-gpl + # text/x-info + # text/x-installshield-lid + # text/x-m4 + # text/x-modulefile + # text/x-ms-adm + # text/x-ms-cpx + # text/x-ms-regedirt + # text/x-ms-tag + # text/x-systemtap + # text/x-vcard + # text/x-wine-extension-reg + # text/x-xmcd + + text/plain) # special filenames. TODO: insert more + case $(basename "$file") in + .zshrc) lexer=sh;; + esac + # pygmentize -N is much cheaper than file, but makes some bad guesses (e.g. + # it guesses ".pl" is Prolog, not Perl) + lexer=$(pygmentize -N "$file") + ;; +esac + +# Find a concatenator for compressed files +concat= +concat_opts= +case $(file $file_common_opts --mime-type "$file") in + # TODO: add support + # application/x-rzip (does not decompress to stdout) + # application/x-dzip (Windows only) + application/gzip|application/x-gzip) concat=zcat;; + application/x-bzip) concat=bzip; concat_opts=-dc;; + application/x-bzip2) concat=bzcat;; + application/x-lz4) concat=lz4; concat_opts=-dc;; + application/x-lzh-compressed) concat=p7zip; concat_opts=-dc;; + application/x-lzma) concat=lzcat;; + application/x-lzip) concat=lzip; concat_opts=-dc;; + application/x-xz) concat=xzcat;; + application/x-zoo) concat=zoo; concat_opts=fu;; +esac +# If concat is unset or doesn't exist, use cat instead +if [[ "$concat" == "" ]] || ! command -v "$concat"; then + concat=cat + concat_opts= +fi + +# Find a suitable reader, preceded by a hex dump for binary files, +# or fmt for text with very long lines +prereader="" +reader=cat +encoding=$(file --mime-encoding --uncompress $file_common_opts "$file") +# FIXME: need a way to switch between hex and text view, as file often +# misdiagnoses files when they contain a few control characters +# if [[ $encoding == "binary" ]]; then +# prereader="od -x" # POSIX fallback +# if [[ -n $(which hd) ]]; then +# prereader=hd # preferred +# fi +# lexer=hexdump +# encoding=latin1 +#el +# FIXME: Using fmt does not work well for system logs +# if [[ "$lexer" == "text" ]]; then +# if file "$file" | grep -ql "text, with very long lines"; then +# reader=fmt +# fi +# fi +if [[ "$lexer" != "text" ]]; then + reader="pygmentize -O inencoding=$encoding $PYGMENTIZE_OPTS $options -l $lexer" +fi + +# Run the reader +if [[ -n "$prereader" ]]; then + exec $concat "$file" | $prereader | $reader +else + exec $concat "$file" | $reader +fi diff --git a/external/lasso-builtins-generator-9.lasso b/external/lasso-builtins-generator-9.lasso new file mode 100755 index 0000000..0156299 --- /dev/null +++ b/external/lasso-builtins-generator-9.lasso @@ -0,0 +1,162 @@ +#!/usr/bin/lasso9 + +/* + Builtins Generator for Lasso 9 + + This is the shell script that was used to extract Lasso 9's built-in keywords + and generate most of the _lasso_builtins.py file. When run, it creates a file + containing the types, traits, methods, and members of the currently-installed + version of Lasso 9. + + A list of tags in Lasso 8 can be generated with this code: + + <?LassoScript + local('l8tags' = list, + 'l8libs' = array('Cache','ChartFX','Client','Database','File','HTTP', + 'iCal','Lasso','Link','List','PDF','Response','Stock','String', + 'Thread','Valid','WAP','XML')); + iterate(#l8libs, local('library')); + local('result' = namespace_load(#library)); + /iterate; + iterate(tags_list, local('i')); + #l8tags->insert(string_removeleading(#i, -pattern='_global_')); + /iterate; + #l8tags->sort; + iterate(#l8tags, local('i')); + string_lowercase(#i)+"<br>"; + /iterate; + +*/ + +output("This output statement is required for a complete list of methods.") +local(f) = file("_lasso_builtins-9.py") +#f->doWithClose => { + +#f->openTruncate +#f->writeString('# -*- coding: utf-8 -*- +""" + pygments.lexers._lasso_builtins + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Built-in Lasso types, traits, methods, and members. + + :copyright: Copyright 2006-'+date->year+' by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +') + +// Load and register contents of $LASSO9_MASTER_HOME/LassoModules/ +database_initialize + +// Load all of the libraries from builtins and lassoserver +// This forces all possible available types and methods to be registered +local(srcs = + (: + dir(sys_masterHomePath + '/LassoLibraries/builtins/')->eachFilePath, + dir(sys_masterHomePath + '/LassoLibraries/lassoserver/')->eachFilePath + ) +) + +with topLevelDir in delve(#srcs) +where not #topLevelDir->lastComponent->beginsWith('.') +do protect => { + handle_error => { + stdoutnl('Unable to load: ' + #topLevelDir + ' ' + error_msg) + } + library_thread_loader->loadLibrary(#topLevelDir) + stdoutnl('Loaded: ' + #topLevelDir) +} + +email_initialize +log_initialize +session_initialize + +local( + typesList = set(), + traitsList = set(), + unboundMethodsList = set(), + memberMethodsList = set() +) + +// types +with type in sys_listTypes +where not #type->asString->endsWith('$') // skip threads +do { + #typesList->insert(#type) +} + +// traits +with trait in sys_listTraits +where not #trait->asString->beginsWith('$') // skip combined traits +do { + #traitsList->insert(#trait) +} + +// member methods +with type in #typesList +do { + with method in #type->getType->listMethods + where #method->typeName == #type // skip inherited methods + let name = #method->methodName + where not #name->asString->endsWith('=') // skip setter methods + where #name->asString->isAlpha(1) // skip unpublished methods + do { + #memberMethodsList->insert(#name) + } +} +with trait in #traitsList +do { + with method in #trait->getType->provides + where #method->typeName == #trait // skip inherited methods + let name = #method->methodName + where not #name->asString->endsWith('=') // skip setter methods + where #name->asString->isAlpha(1) // skip unpublished methods + do { + #memberMethodsList->insert(#name) + } +} + +// unbound methods +with method in sys_listUnboundMethods +let name = #method->methodName +where not #name->asString->endsWith('=') // skip setter methods +where #name->asString->isAlpha(1) // skip unpublished methods +where #typesList !>> #name +where #traitsList !>> #name +do { + #unboundMethodsList->insert(#name) +} + +// write to file +with i in (: + pair(#typesList, "BUILTINS = { + 'Types': ( +"), + pair(#traitsList, " ), + 'Traits': ( +"), + pair(#unboundMethodsList, " ), + 'Unbound Methods': ( +"), + pair(#memberMethodsList, " ) +} +MEMBERS = { + 'Member Methods': ( +") +) +do { + #f->writeString(#i->second) + with t in (#i->first) + let ts = #t->asString + order by #ts + do { + #f->writeString(" '"+#ts->lowercase&asString+"',\n") + } +} + +#f->writeString(" ) +} +") + +} diff --git a/external/lilypond-builtins-generator.ly b/external/lilypond-builtins-generator.ly new file mode 100644 index 0000000..983b4c3 --- /dev/null +++ b/external/lilypond-builtins-generator.ly @@ -0,0 +1,391 @@ +%% Autogenerate a list of LilyPond keywords + +\version "2.23.6" + +#(use-modules (ice-9 receive) + (ice-9 regex)) + +#(define port (open-output-file "../pygments/lexers/_lilypond_builtins.py")) + +#(define output-preamble + "\"\"\" + pygments.lexers._lilypond_builtins + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + LilyPond builtins. + + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +\"\"\" + +# Contents generated by the script lilypond-builtins-generator.ly +# found in the external/ directory of the source tree. + +") + +#(format port "~a" output-preamble) + +#(define (dump-py-list name vals) + (let* ((string-vals + (map symbol->string vals)) + (fixed-vals + (filter-map + (lambda (str) + ; To avoid conflicts with Scheme builtins, + ; a leading backslash is prepended to \<, + ; \= and a few others. The lexer finds it + ; itself, so remove it here. + (cond + ((equal? str "\\\\") + #f) + ((string-startswith str "\\") + (string-drop str 1)) + (else + str))) + string-vals)) + (sorted-vals ; reproducibility + ; Avoid duplicates (e.g., identical pitches + ; in different languages) + (uniq-list + (sort fixed-vals string<?))) + (formatted-vals + (map + (lambda (val) + (format #f " \"~a\"," val name)) + sorted-vals)) + (joint-vals + (string-join formatted-vals "\n"))) + (format port + "~a = [ +~a +] + +" + name + joint-vals))) + + +%% KEYWORDS + +#(define keywords + '( + ; Lexical modes. + notemode + lyricmode + lyricsto + addlyrics + chordmode + chords + figuremode + figures + drummode + drums + ; Output definitions. + header + layout + midi + paper + ; Context definitions. + ;; \context is also used in music. We take it as + ;; a keyword in both cases. + context + with + name + type + accepts + denies + alias + defaultchild + consists + remove + description + ;; Not strictly a keyword, but can be viewed so. + inherit-acceptability + ; Blocks. + book + bookpart + score + ; Other. + new + etc + include + language + version)) + +#(dump-py-list 'keywords keywords) + +%% CLEFS + +#(define all-clefs + (map string->symbol (map car supported-clefs))) + +#(dump-py-list 'clefs all-clefs) + +%% SCALES + +#(define all-scales + '(major + minor + ionian + locrian + aeolian + mixolydian + lydian + phrygian + dorian)) + +#(dump-py-list 'scales all-scales) + +%% REPEAT TYPES + +#(define all-repeat-types + '(volta percent unfold segno)) + +#(dump-py-list 'repeat_types all-repeat-types) + +%% UNITS + +#(define all-units + '(mm cm in pt staff-space)) + +#(dump-py-list 'units all-units) + +%% CHORD MODIFIERS + +#(define all-chord-modifiers + '(m dim aug maj)) + +#(dump-py-list 'chord_modifiers all-chord-modifiers) + +%% PITCHES + +#(define all-pitch-language-names + (map car language-pitch-names)) + +#(dump-py-list 'pitch_language_names all-pitch-language-names) + +#(define all-pitch-names + (append + ; We highlight rests just like pitches. + '(r R) + (map car (append-map cdr language-pitch-names)) + ; Drum note names. + (map car drumPitchNames))) + +#(dump-py-list 'pitches all-pitch-names) + +%% MUSIC FUNCTIONS AND SHORTCUTS + +% View these as music functions. +#(define extra-music-functions + '(set + unset + override + revert + tweak + once + undo + temporary + repeat + alternative + tempo + change)) + +#(let* ((module (current-module)) + (module-alist (ly:module->alist module)) + (all-music-functions + (filter + (lambda (entry) + (ly:music-function? (cdr entry))) + module-alist)) + (all-predefined-music-objects + (filter + (lambda (entry) + (ly:music? (cdr entry))) + module-alist))) + (receive (articulations non-articulations) + (partition + (lambda (entry) + (ly:event? (cdr entry))) + all-predefined-music-objects) + (receive (dynamics non-dynamic-articulations) + (partition + (lambda (entry) + (any + (lambda (type) + (music-is-of-type? (cdr entry) + type)) + '(dynamic-event crescendo-event decrescendo-event))) + articulations) + (dump-py-list 'music_functions + (append extra-music-functions + (map car all-music-functions))) + (dump-py-list 'dynamics (map car dynamics)) + (dump-py-list 'articulations (map car non-dynamic-articulations)) + (dump-py-list 'music_commands (map car non-articulations))))) + +%% MARKUP COMMANDS + +#(let* ((markup-name-regexp + (make-regexp "(.*)-markup(-list)?")) + (modules + (cons (current-module) + (map resolve-module '((lily) (lily accreg))))) + (alist + (apply append + (map ly:module->alist modules))) + (markup-commands + (filter + (lambda (entry) + (or (markup-function? (cdr entry)) + (markup-list-function? (cdr entry)))) + alist)) + (markup-command-names + (map + (lambda (entry) + (let* ((string-name (symbol->string (car entry))) + (match (regexp-exec markup-name-regexp string-name))) + (string->symbol (match:substring match 1)))) + markup-commands)) + (markup-words + (append '(markup markuplist) + markup-command-names))) + (dump-py-list 'markup_commands markup-words)) + +%% GROBS + +#(let ((grob-names (map car all-grob-descriptions))) + (dump-py-list 'grobs grob-names)) + +%% CONTEXTS + +#(let* ((layout-module + (ly:output-def-scope $defaultlayout)) + (layout-alist + (ly:module->alist layout-module)) + (all-context-defs + (filter + (lambda (entry) + (ly:context-def? (cdr entry))) + layout-alist)) + (context-def-names + (map car all-context-defs))) + (dump-py-list 'contexts context-def-names)) + +%% TRANSLATORS + +#(let* ((all-translators + (ly:get-all-translators)) + (translator-names + (map ly:translator-name all-translators))) + (dump-py-list 'translators translator-names)) + +%% SCHEME FUNCTIONS + +#(let* ((module (resolve-module '(lily))) + (module-alist (ly:module->alist module)) + (all-functions + (filter + (lambda (entry) + (or (procedure? (cdr entry)) + (macro? (cdr entry)))) + module-alist)) + (all-function-names + (map car all-functions))) + (dump-py-list 'scheme_functions all-function-names)) + +%% PROPERTIES + +#(dump-py-list 'context_properties all-translation-properties) +#(dump-py-list 'grob_properties all-backend-properties) + +%% PAPER VARIABLES + +% Reference: https://lilypond.org/doc/v2.22/Documentation/notation/page-layout +#(define all-paper-variables + '(paper-height + top-margin + bottom-margin + ragged-bottom + ragged-last-bottom + markup-system-spacing + score-markup-spacing + score-system-spacing + system-system-spacing + markup-markup-spacing + last-bottom-spacing + top-system-spacing + top-markup-spacing + paper-width + line-width + left-margin + right-margin + check-consistency + ragged-right + ragged-last + two-sided + inner-margin + outer-margin + binding-offset + horizontal-shift + indent + short-indent + max-systems-per-page + min-systems-per-page + systems-per-page + system-count + page-breaking + page-breaking-system-system-spacing + page-count + blank-page-penalty + blank-last-page-penalty + auto-first-page-number + first-page-number + print-first-page-number + page-number-type + page-spacing-weight + print-all-headers + system-separator-markup + footnote-separator-markup + ;; Let's view these four as \paper variables. + basic-distance + minimum-distance + padding + stretchability + ;; These were forgotten in the documentation. + evenHeaderMarkup + oddHeaderMarkup + evenFooterMarkup + oddFooterMarkup + bookTitleMarkup + scoreTitleMarkup + )) + +#(dump-py-list 'paper_variables all-paper-variables) + +%% HEADER VARIABLES + +% Reference: https://lilypond.org/doc/v2.22/Documentation/notation/creating-titles-headers-and-footers.html#default-layout-of-bookpart-and-score-titles +#(define all-header-variables + '(dedication + title + subtitle + subsubtitle + instrument + poet + composer + meter + arranger + tagline + copyright + piece + opus + ; The following are used in LSR snippets and regression tests. + lsrtags + doctitle + texidoc)) + +#(dump-py-list 'header_variables all-header-variables) + + +#(close-port port) diff --git a/external/markdown-processor.py b/external/markdown-processor.py new file mode 100644 index 0000000..d72012f --- /dev/null +++ b/external/markdown-processor.py @@ -0,0 +1,66 @@ +""" + The Pygments Markdown Preprocessor + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + This fragment is a Markdown_ preprocessor that renders source code + to HTML via Pygments. To use it, invoke Markdown like so:: + + import markdown + + html = markdown.markdown(someText, extensions=[CodeBlockExtension()]) + + This uses CSS classes by default, so use + ``pygmentize -S <some style> -f html > pygments.css`` + to create a stylesheet to be added to the website. + + You can then highlight source code in your markdown markup:: + + [sourcecode:lexer] + some code + [/sourcecode] + + .. _Markdown: https://pypi.python.org/pypi/Markdown + + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +# Options +# ~~~~~~~ + +# Set to True if you want inline CSS styles instead of classes +INLINESTYLES = False + + +import re + +from markdown.preprocessors import Preprocessor +from markdown.extensions import Extension + +from pygments import highlight +from pygments.formatters import HtmlFormatter +from pygments.lexers import get_lexer_by_name, TextLexer + + +class CodeBlockPreprocessor(Preprocessor): + + pattern = re.compile(r'\[sourcecode:(.+?)\](.+?)\[/sourcecode\]', re.S) + + formatter = HtmlFormatter(noclasses=INLINESTYLES) + + def run(self, lines): + def repl(m): + try: + lexer = get_lexer_by_name(m.group(1)) + except ValueError: + lexer = TextLexer() + code = highlight(m.group(2), lexer, self.formatter) + code = code.replace('\n\n', '\n \n').replace('\n', '<br />') + return '\n\n<div class="code">%s</div>\n\n' % code + joined_lines = "\n".join(lines) + joined_lines = self.pattern.sub(repl, joined_lines) + return joined_lines.split("\n") + +class CodeBlockExtension(Extension): + def extendMarkdown(self, md, md_globals): + md.preprocessors.add('CodeBlockPreprocessor', CodeBlockPreprocessor(), '_begin') diff --git a/external/moin-parser.py b/external/moin-parser.py new file mode 100644 index 0000000..562b76f --- /dev/null +++ b/external/moin-parser.py @@ -0,0 +1,111 @@ +""" + The Pygments MoinMoin Parser + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + This is a MoinMoin parser plugin that renders source code to HTML via + Pygments; you need Pygments 0.7 or newer for this parser to work. + + To use it, set the options below to match your setup and put this file in + the data/plugin/parser subdirectory of your Moin instance, and give it the + name that the parser directive should have. For example, if you name the + file ``code.py``, you can get a highlighted Python code sample with this + Wiki markup:: + + {{{ + #!code python + [...] + }}} + + Additionally, if you set ATTACHMENTS below to True, Pygments will also be + called for all attachments for whose filenames there is no other parser + registered. + + You are responsible for including CSS rules that will map the Pygments CSS + classes to colors. You can output a stylesheet file with `pygmentize`, put + it into the `htdocs` directory of your Moin instance and then include it in + the `stylesheets` configuration option in the Moin config, e.g.:: + + stylesheets = [('screen', '/htdocs/pygments.css')] + + If you do not want to do that and are willing to accept larger HTML + output, you can set the INLINESTYLES option below to True. + + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +# Options +# ~~~~~~~ + +# Set to True if you want to highlight attachments, in addition to +# {{{ }}} blocks. +ATTACHMENTS = True + +# Set to True if you want inline CSS styles instead of classes +INLINESTYLES = False + + +import sys + +from pygments import highlight +from pygments.lexers import get_lexer_by_name, get_lexer_for_filename, TextLexer +from pygments.formatters import HtmlFormatter +from pygments.util import ClassNotFound + + +# wrap lines in <span>s so that the Moin-generated line numbers work +class MoinHtmlFormatter(HtmlFormatter): + def wrap(self, source, outfile): + for line in source: + yield 1, '<span class="line">' + line[1] + '</span>' + +htmlformatter = MoinHtmlFormatter(noclasses=INLINESTYLES) +textlexer = TextLexer() +codeid = [0] + + +class Parser: + """ + MoinMoin Pygments parser. + """ + if ATTACHMENTS: + extensions = '*' + else: + extensions = [] + + Dependencies = [] + + def __init__(self, raw, request, **kw): + self.raw = raw + self.req = request + if "format_args" in kw: + # called from a {{{ }}} block + try: + self.lexer = get_lexer_by_name(kw['format_args'].strip()) + except ClassNotFound: + self.lexer = textlexer + return + if "filename" in kw: + # called for an attachment + filename = kw['filename'] + else: + # called for an attachment by an older moin + # HACK: find out the filename by peeking into the execution + # frame which might not always work + try: + frame = sys._getframe(1) + filename = frame.f_locals['filename'] + except: + filename = 'x.txt' + try: + self.lexer = get_lexer_for_filename(filename) + except ClassNotFound: + self.lexer = textlexer + + def format(self, formatter): + codeid[0] += 1 + id = "pygments_%s" % codeid[0] + w = self.req.write + w(formatter.code_area(1, id, start=1, step=1)) + w(formatter.rawHTML(highlight(self.raw, self.lexer, htmlformatter))) + w(formatter.code_area(0, id)) diff --git a/external/pygments.bashcomp b/external/pygments.bashcomp new file mode 100644 index 0000000..1299fdb --- /dev/null +++ b/external/pygments.bashcomp @@ -0,0 +1,38 @@ +#!bash +# +# Bash completion support for Pygments (the 'pygmentize' command). +# + +_pygmentize() +{ + local cur prev + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + case "$prev" in + -f) + FORMATTERS=`pygmentize -L formatters | grep '* ' | cut -c3- | sed -e 's/,//g' -e 's/:$//'` + COMPREPLY=( $( compgen -W '$FORMATTERS' -- "$cur" ) ) + return 0 + ;; + -l) + LEXERS=`pygmentize -L lexers | grep '* ' | cut -c3- | sed -e 's/,//g' -e 's/:$//'` + COMPREPLY=( $( compgen -W '$LEXERS' -- "$cur" ) ) + return 0 + ;; + -S) + STYLES=`pygmentize -L styles | grep '* ' | cut -c3- | sed s/:$//` + COMPREPLY=( $( compgen -W '$STYLES' -- "$cur" ) ) + return 0 + ;; + esac + + if [[ "$cur" == -* ]]; then + COMPREPLY=( $( compgen -W '-f -l -S -L -g -O -P -F \ + -N -H -h -V -o' -- "$cur" ) ) + return 0 + fi +} +complete -F _pygmentize -o default pygmentize diff --git a/external/rst-directive.py b/external/rst-directive.py new file mode 100644 index 0000000..5872185 --- /dev/null +++ b/external/rst-directive.py @@ -0,0 +1,81 @@ +""" + The Pygments reStructuredText directive + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + This fragment is a Docutils_ 0.5 directive that renders source code + (to HTML only, currently) via Pygments. + + To use it, adjust the options below and copy the code into a module + that you import on initialization. The code then automatically + registers a ``sourcecode`` directive that you can use instead of + normal code blocks like this:: + + .. sourcecode:: python + + My code goes here. + + If you want to have different code styles, e.g. one with line numbers + and one without, add formatters with their names in the VARIANTS dict + below. You can invoke them instead of the DEFAULT one by using a + directive option:: + + .. sourcecode:: python + :linenos: + + My code goes here. + + Look at the `directive documentation`_ to get all the gory details. + + .. _Docutils: https://docutils.sourceforge.io/ + .. _directive documentation: + https://docutils.sourceforge.io/docs/howto/rst-directives.html + + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +# Options +# ~~~~~~~ + +# Set to True if you want inline CSS styles instead of classes +INLINESTYLES = False + +from pygments.formatters import HtmlFormatter + +# The default formatter +DEFAULT = HtmlFormatter(noclasses=INLINESTYLES) + +# Add name -> formatter pairs for every variant you want to use +VARIANTS = { + # 'linenos': HtmlFormatter(noclasses=INLINESTYLES, linenos=True), +} + + +from docutils import nodes +from docutils.parsers.rst import directives, Directive + +from pygments import highlight +from pygments.lexers import get_lexer_by_name, TextLexer + +class Pygments(Directive): + """ Source code syntax highlighting. + """ + required_arguments = 1 + optional_arguments = 0 + final_argument_whitespace = True + option_spec = {key: directives.flag for key in VARIANTS} + has_content = True + + def run(self): + self.assert_has_content() + try: + lexer = get_lexer_by_name(self.arguments[0]) + except ValueError: + # no lexer found - use the text one instead of an exception + lexer = TextLexer() + # take an arbitrary option if more than one is given + formatter = self.options and VARIANTS[list(self.options)[0]] or DEFAULT + parsed = highlight('\n'.join(self.content), lexer, formatter) + return [nodes.raw('', parsed, format='html')] + +directives.register_directive('sourcecode', Pygments) diff --git a/external/scheme-builtins-generator.scm b/external/scheme-builtins-generator.scm new file mode 100644 index 0000000..5c260b8 --- /dev/null +++ b/external/scheme-builtins-generator.scm @@ -0,0 +1,116 @@ +;; Autogenerate a list of Scheme keywords (i.e., macros) and built-in +;; functions. This is written for the Guile implementation. The +;; principle of autogenerating this has the advantage of catching many +;; builtins that would be tedious to maintain by hand, and the +;; disadvantage that some builtins very specific to Guile and not +;; relevant to other implementations are caught as well. However, +;; since Scheme builtin function names tend to be rather specific, +;; this should not be a significant problem. + +(define port (open-output-file "../pygments/lexers/_scheme_builtins.py")) + +(display + "\"\"\" + pygments.lexers._scheme_builtins + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Scheme builtins. + + :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +\"\"\" +" + port) + +(format port +"\n# Autogenerated by external/scheme-builtins-generator.scm\n\ +# using Guile ~a.\n\n" + (version)) + +(use-modules (srfi srfi-1) + (ice-9 match)) + +(define relevant-modules + ;; This is a nightmare. Scheme builtins are split in + ;; gazillions of standards, SRFIs and implementation + ;; extensions. With so many sources, it's hard to define + ;; what is really a Scheme builtin. This is a rather + ;; conservative list of Guile modules that might be used + ;; the most frequently (somewhat subjective, admittedly). + '( + ;; The real builtins. + (guile) + ;; Let's include the fundamental list library. + (srfi srfi-1) + ;; define-record-type + (srfi srfi-9) + ;; let-values, let*-values + (srfi srfi-11) + ;; case-lambda + (srfi srfi-16) + ;; Pattern matching + (ice-9 match) + ;; Included for compatibility with files written for R5RS + (rnrs r5rs))) + +(define (get-all-bindings module) + ;; Need to recurse to find all public bindings. module-map + ;; only considers the module's own bindings. + (let* ((own (module-map cons module)) + (uses (module-uses module))) + (append own (append-map get-all-bindings uses)))) + +(define all-bindings + (append-map + ;; Need to use module-public-interface to restrict to + ;; public bindings. Note that module-uses already + ;; returns public interfaces. + (lambda (mod-path) + (let* ((mod-object (resolve-module mod-path)) + (iface (module-public-interface mod-object))) + (get-all-bindings iface))) + relevant-modules)) + +(define (filter-for pred) + (filter-map + (match-lambda + ((key . variable) + (and (variable-bound? variable) + (let ((value (variable-ref variable))) + (and (pred value) + key))))) + all-bindings)) + +(define (sort-and-uniq lst pred) + (let loop ((lst (sort lst pred)) + (acc '())) + (match lst + (() (reverse! acc)) + ((one . rest) + (loop (drop-while (lambda (elt) + (equal? elt one)) + rest) + (cons one acc)))))) + +(define (dump-py-list lst) + (string-join + (map + (lambda (name) + (format #f " \"~a\"," name)) + (sort-and-uniq + (map symbol->string lst) + string<?)) + "\n")) + +(define (dump-builtins name pred extra) + (format port + "~a = {\n~a\n}\n\n" + name + (dump-py-list (append extra (filter-for pred))))) + +(define extra-procedures + ;; These are found in RnRS but not implemented by Guile. + '(load transcript-off transcript-on)) + +(dump-builtins 'scheme_keywords macro? '()) +(dump-builtins 'scheme_builtins procedure? extra-procedures) |