]> git.bundesbrandschatzamt.de Git - emacsconfig.git/commitdiff
add missing dependency packages
authorAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Sat, 2 Nov 2019 12:52:01 +0000 (13:52 +0100)
committerAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Sat, 2 Nov 2019 12:52:01 +0000 (13:52 +0100)
18 files changed:
elpa/julia-mode-20191002.1352/julia-latexsubs.el [new file with mode: 0644]
elpa/julia-mode-20191002.1352/julia-mode-autoloads.el [new file with mode: 0644]
elpa/julia-mode-20191002.1352/julia-mode-pkg.el [new file with mode: 0644]
elpa/julia-mode-20191002.1352/julia-mode.el [new file with mode: 0644]
elpa/julia-mode-readme.txt [new file with mode: 0644]
elpa/pcre2el-20161120.2103/pcre2el-autoloads.el [new file with mode: 0644]
elpa/pcre2el-20161120.2103/pcre2el-pkg.el [new file with mode: 0644]
elpa/pcre2el-20161120.2103/pcre2el.el [new file with mode: 0644]
elpa/pcre2el-readme.txt [new file with mode: 0644]
elpa/sesman-20190909.1754/sesman-autoloads.el [new file with mode: 0644]
elpa/sesman-20190909.1754/sesman-browser.el [new file with mode: 0644]
elpa/sesman-20190909.1754/sesman-pkg.el [new file with mode: 0644]
elpa/sesman-20190909.1754/sesman.el [new file with mode: 0644]
elpa/sesman-readme.txt [new file with mode: 0644]
elpa/xml+-20170727.2351/xml+-autoloads.el [new file with mode: 0644]
elpa/xml+-20170727.2351/xml+-pkg.el [new file with mode: 0644]
elpa/xml+-20170727.2351/xml+.el [new file with mode: 0644]
elpa/xml+-readme.txt [new file with mode: 0644]

diff --git a/elpa/julia-mode-20191002.1352/julia-latexsubs.el b/elpa/julia-mode-20191002.1352/julia-latexsubs.el
new file mode 100644 (file)
index 0000000..6d07080
--- /dev/null
@@ -0,0 +1,3324 @@
+(puthash "\\exclamdown" "¡" julia-latexsubs)
+(puthash "\\sterling" "£" julia-latexsubs)
+(puthash "\\yen" "¥" julia-latexsubs)
+(puthash "\\brokenbar" "¦" julia-latexsubs)
+(puthash "\\S" "§" julia-latexsubs)
+(puthash "\\copyright" "©" julia-latexsubs)
+(puthash "\\:copyright:" "©" julia-latexsubs)
+(puthash "\\ordfeminine" "ª" julia-latexsubs)
+(puthash "\\neg" "¬" julia-latexsubs)
+(puthash "\\:registered:" "®" julia-latexsubs)
+(puthash "\\circledR" "®" julia-latexsubs)
+(puthash "\\highminus" "¯" julia-latexsubs)
+(puthash "\\degree" "°" julia-latexsubs)
+(puthash "\\pm" "±" julia-latexsubs)
+(puthash "\\^2" "²" julia-latexsubs)
+(puthash "\\^3" "³" julia-latexsubs)
+(puthash "\\P" "¶" julia-latexsubs)
+(puthash "\\cdotp" "·" julia-latexsubs)
+(puthash "\\^1" "¹" julia-latexsubs)
+(puthash "\\ordmasculine" "º" julia-latexsubs)
+(puthash "\\1/4" "¼" julia-latexsubs)
+(puthash "\\1/2" "½" julia-latexsubs)
+(puthash "\\3/4" "¾" julia-latexsubs)
+(puthash "\\questiondown" "¿" julia-latexsubs)
+(puthash "\\AA" "Å" julia-latexsubs)
+(puthash "\\AE" "Æ" julia-latexsubs)
+(puthash "\\DH" "Ð" julia-latexsubs)
+(puthash "\\times" "×" julia-latexsubs)
+(puthash "\\O" "Ø" julia-latexsubs)
+(puthash "\\TH" "Þ" julia-latexsubs)
+(puthash "\\ss" "ß" julia-latexsubs)
+(puthash "\\aa" "å" julia-latexsubs)
+(puthash "\\ae" "æ" julia-latexsubs)
+(puthash "\\eth" "ð" julia-latexsubs)
+(puthash "\\dh" "ð" julia-latexsubs)
+(puthash "\\div" "÷" julia-latexsubs)
+(puthash "\\o" "ø" julia-latexsubs)
+(puthash "\\th" "þ" julia-latexsubs)
+(puthash "\\DJ" "Đ" julia-latexsubs)
+(puthash "\\dj" "đ" julia-latexsubs)
+(puthash "\\hbar" "ħ" julia-latexsubs)
+(puthash "\\imath" "ı" julia-latexsubs)
+(puthash "\\L" "Ł" julia-latexsubs)
+(puthash "\\l" "ł" julia-latexsubs)
+(puthash "\\NG" "Ŋ" julia-latexsubs)
+(puthash "\\ng" "ŋ" julia-latexsubs)
+(puthash "\\OE" "Œ" julia-latexsubs)
+(puthash "\\oe" "œ" julia-latexsubs)
+(puthash "\\hvlig" "ƕ" julia-latexsubs)
+(puthash "\\nrleg" "ƞ" julia-latexsubs)
+(puthash "\\Zbar" "Ƶ" julia-latexsubs)
+(puthash "\\doublepipe" "ǂ" julia-latexsubs)
+(puthash "\\jmath" "ȷ" julia-latexsubs)
+(puthash "\\trna" "ɐ" julia-latexsubs)
+(puthash "\\trnsa" "ɒ" julia-latexsubs)
+(puthash "\\openo" "ɔ" julia-latexsubs)
+(puthash "\\rtld" "ɖ" julia-latexsubs)
+(puthash "\\schwa" "ə" julia-latexsubs)
+(puthash "\\pgamma" "ɣ" julia-latexsubs)
+(puthash "\\pbgam" "ɤ" julia-latexsubs)
+(puthash "\\trnh" "ɥ" julia-latexsubs)
+(puthash "\\btdl" "ɬ" julia-latexsubs)
+(puthash "\\rtll" "ɭ" julia-latexsubs)
+(puthash "\\trnm" "ɯ" julia-latexsubs)
+(puthash "\\trnmlr" "ɰ" julia-latexsubs)
+(puthash "\\ltlmr" "ɱ" julia-latexsubs)
+(puthash "\\ltln" "ɲ" julia-latexsubs)
+(puthash "\\rtln" "ɳ" julia-latexsubs)
+(puthash "\\clomeg" "ɷ" julia-latexsubs)
+(puthash "\\ltphi" "ɸ" julia-latexsubs)
+(puthash "\\trnr" "ɹ" julia-latexsubs)
+(puthash "\\trnrl" "ɺ" julia-latexsubs)
+(puthash "\\rttrnr" "ɻ" julia-latexsubs)
+(puthash "\\rl" "ɼ" julia-latexsubs)
+(puthash "\\rtlr" "ɽ" julia-latexsubs)
+(puthash "\\fhr" "ɾ" julia-latexsubs)
+(puthash "\\rtls" "ʂ" julia-latexsubs)
+(puthash "\\esh" "ʃ" julia-latexsubs)
+(puthash "\\trnt" "ʇ" julia-latexsubs)
+(puthash "\\rtlt" "ʈ" julia-latexsubs)
+(puthash "\\pupsil" "ʊ" julia-latexsubs)
+(puthash "\\pscrv" "ʋ" julia-latexsubs)
+(puthash "\\invv" "ʌ" julia-latexsubs)
+(puthash "\\invw" "ʍ" julia-latexsubs)
+(puthash "\\trny" "ʎ" julia-latexsubs)
+(puthash "\\rtlz" "ʐ" julia-latexsubs)
+(puthash "\\yogh" "ʒ" julia-latexsubs)
+(puthash "\\glst" "ʔ" julia-latexsubs)
+(puthash "\\reglst" "ʕ" julia-latexsubs)
+(puthash "\\inglst" "ʖ" julia-latexsubs)
+(puthash "\\turnk" "ʞ" julia-latexsubs)
+(puthash "\\dyogh" "ʤ" julia-latexsubs)
+(puthash "\\tesh" "ʧ" julia-latexsubs)
+(puthash "\\^h" "ʰ" julia-latexsubs)
+(puthash "\\^j" "ʲ" julia-latexsubs)
+(puthash "\\^r" "ʳ" julia-latexsubs)
+(puthash "\\^w" "ʷ" julia-latexsubs)
+(puthash "\\^y" "ʸ" julia-latexsubs)
+(puthash "\\rasp" "ʼ" julia-latexsubs)
+(puthash "\\verts" "ˈ" julia-latexsubs)
+(puthash "\\verti" "ˌ" julia-latexsubs)
+(puthash "\\lmrk" "ː" julia-latexsubs)
+(puthash "\\hlmrk" "ˑ" julia-latexsubs)
+(puthash "\\sbrhr" "˒" julia-latexsubs)
+(puthash "\\sblhr" "˓" julia-latexsubs)
+(puthash "\\rais" "˔" julia-latexsubs)
+(puthash "\\low" "˕" julia-latexsubs)
+(puthash "\\u" "˘" julia-latexsubs)
+(puthash "\\tildelow" "˜" julia-latexsubs)
+(puthash "\\^l" "ˡ" julia-latexsubs)
+(puthash "\\^s" "ˢ" julia-latexsubs)
+(puthash "\\^x" "ˣ" julia-latexsubs)
+(puthash "\\grave" "̀" julia-latexsubs)
+(puthash "\\acute" "́" julia-latexsubs)
+(puthash "\\hat" "̂" julia-latexsubs)
+(puthash "\\tilde" "̃" julia-latexsubs)
+(puthash "\\bar" "̄" julia-latexsubs)
+(puthash "\\overbar" "̅" julia-latexsubs)
+(puthash "\\breve" "̆" julia-latexsubs)
+(puthash "\\dot" "̇" julia-latexsubs)
+(puthash "\\ddot" "̈" julia-latexsubs)
+(puthash "\\ovhook" "̉" julia-latexsubs)
+(puthash "\\ocirc" "̊" julia-latexsubs)
+(puthash "\\H" "̋" julia-latexsubs)
+(puthash "\\check" "̌" julia-latexsubs)
+(puthash "\\candra" "̐" julia-latexsubs)
+(puthash "\\oturnedcomma" "̒" julia-latexsubs)
+(puthash "\\ocommatopright" "̕" julia-latexsubs)
+(puthash "\\droang" "̚" julia-latexsubs)
+(puthash "\\palh" "̡" julia-latexsubs)
+(puthash "\\rh" "̢" julia-latexsubs)
+(puthash "\\c" "̧" julia-latexsubs)
+(puthash "\\k" "̨" julia-latexsubs)
+(puthash "\\sbbrg" "̪" julia-latexsubs)
+(puthash "\\wideutilde" "̰" julia-latexsubs)
+(puthash "\\underbar" "̲" julia-latexsubs)
+(puthash "\\strike" "̶" julia-latexsubs)
+(puthash "\\sout" "̶" julia-latexsubs)
+(puthash "\\not" "̸" julia-latexsubs)
+(puthash "\\underleftrightarrow" "͍" julia-latexsubs)
+(puthash "\\Alpha" "Α" julia-latexsubs)
+(puthash "\\Beta" "Β" julia-latexsubs)
+(puthash "\\Gamma" "Γ" julia-latexsubs)
+(puthash "\\Delta" "Δ" julia-latexsubs)
+(puthash "\\Epsilon" "Ε" julia-latexsubs)
+(puthash "\\Zeta" "Ζ" julia-latexsubs)
+(puthash "\\Eta" "Η" julia-latexsubs)
+(puthash "\\Theta" "Θ" julia-latexsubs)
+(puthash "\\Iota" "Ι" julia-latexsubs)
+(puthash "\\Kappa" "Κ" julia-latexsubs)
+(puthash "\\Lambda" "Λ" julia-latexsubs)
+(puthash "\\upMu" "Μ" julia-latexsubs)
+(puthash "\\upNu" "Ν" julia-latexsubs)
+(puthash "\\Xi" "Ξ" julia-latexsubs)
+(puthash "\\upOmicron" "Ο" julia-latexsubs)
+(puthash "\\Pi" "Π" julia-latexsubs)
+(puthash "\\Rho" "Ρ" julia-latexsubs)
+(puthash "\\Sigma" "Σ" julia-latexsubs)
+(puthash "\\Tau" "Τ" julia-latexsubs)
+(puthash "\\Upsilon" "Υ" julia-latexsubs)
+(puthash "\\Phi" "Φ" julia-latexsubs)
+(puthash "\\Chi" "Χ" julia-latexsubs)
+(puthash "\\Psi" "Ψ" julia-latexsubs)
+(puthash "\\Omega" "Ω" julia-latexsubs)
+(puthash "\\alpha" "α" julia-latexsubs)
+(puthash "\\beta" "β" julia-latexsubs)
+(puthash "\\gamma" "γ" julia-latexsubs)
+(puthash "\\delta" "δ" julia-latexsubs)
+(puthash "\\upepsilon" "ε" julia-latexsubs)
+(puthash "\\varepsilon" "ε" julia-latexsubs)
+(puthash "\\zeta" "ζ" julia-latexsubs)
+(puthash "\\eta" "η" julia-latexsubs)
+(puthash "\\theta" "θ" julia-latexsubs)
+(puthash "\\iota" "ι" julia-latexsubs)
+(puthash "\\kappa" "κ" julia-latexsubs)
+(puthash "\\lambda" "λ" julia-latexsubs)
+(puthash "\\mu" "μ" julia-latexsubs)
+(puthash "\\nu" "ν" julia-latexsubs)
+(puthash "\\xi" "ξ" julia-latexsubs)
+(puthash "\\upomicron" "ο" julia-latexsubs)
+(puthash "\\pi" "π" julia-latexsubs)
+(puthash "\\rho" "ρ" julia-latexsubs)
+(puthash "\\varsigma" "ς" julia-latexsubs)
+(puthash "\\sigma" "σ" julia-latexsubs)
+(puthash "\\tau" "τ" julia-latexsubs)
+(puthash "\\upsilon" "υ" julia-latexsubs)
+(puthash "\\varphi" "φ" julia-latexsubs)
+(puthash "\\chi" "χ" julia-latexsubs)
+(puthash "\\psi" "ψ" julia-latexsubs)
+(puthash "\\omega" "ω" julia-latexsubs)
+(puthash "\\upvarbeta" "ϐ" julia-latexsubs)
+(puthash "\\vartheta" "ϑ" julia-latexsubs)
+(puthash "\\phi" "ϕ" julia-latexsubs)
+(puthash "\\varpi" "ϖ" julia-latexsubs)
+(puthash "\\upoldKoppa" "Ϙ" julia-latexsubs)
+(puthash "\\upoldkoppa" "ϙ" julia-latexsubs)
+(puthash "\\Stigma" "Ϛ" julia-latexsubs)
+(puthash "\\upstigma" "ϛ" julia-latexsubs)
+(puthash "\\Digamma" "Ϝ" julia-latexsubs)
+(puthash "\\digamma" "ϝ" julia-latexsubs)
+(puthash "\\Koppa" "Ϟ" julia-latexsubs)
+(puthash "\\upkoppa" "ϟ" julia-latexsubs)
+(puthash "\\Sampi" "Ϡ" julia-latexsubs)
+(puthash "\\upsampi" "ϡ" julia-latexsubs)
+(puthash "\\varkappa" "ϰ" julia-latexsubs)
+(puthash "\\varrho" "ϱ" julia-latexsubs)
+(puthash "\\varTheta" "ϴ" julia-latexsubs)
+(puthash "\\epsilon" "ϵ" julia-latexsubs)
+(puthash "\\backepsilon" "϶" julia-latexsubs)
+(puthash "\\^A" "ᴬ" julia-latexsubs)
+(puthash "\\^B" "ᴮ" julia-latexsubs)
+(puthash "\\^D" "ᴰ" julia-latexsubs)
+(puthash "\\^E" "ᴱ" julia-latexsubs)
+(puthash "\\^G" "ᴳ" julia-latexsubs)
+(puthash "\\^H" "ᴴ" julia-latexsubs)
+(puthash "\\^I" "ᴵ" julia-latexsubs)
+(puthash "\\^J" "ᴶ" julia-latexsubs)
+(puthash "\\^K" "ᴷ" julia-latexsubs)
+(puthash "\\^L" "ᴸ" julia-latexsubs)
+(puthash "\\^M" "ᴹ" julia-latexsubs)
+(puthash "\\^N" "ᴺ" julia-latexsubs)
+(puthash "\\^O" "ᴼ" julia-latexsubs)
+(puthash "\\^P" "ᴾ" julia-latexsubs)
+(puthash "\\^R" "ᴿ" julia-latexsubs)
+(puthash "\\^T" "ᵀ" julia-latexsubs)
+(puthash "\\^U" "ᵁ" julia-latexsubs)
+(puthash "\\^W" "ᵂ" julia-latexsubs)
+(puthash "\\^a" "ᵃ" julia-latexsubs)
+(puthash "\\^alpha" "ᵅ" julia-latexsubs)
+(puthash "\\^b" "ᵇ" julia-latexsubs)
+(puthash "\\^d" "ᵈ" julia-latexsubs)
+(puthash "\\^e" "ᵉ" julia-latexsubs)
+(puthash "\\^epsilon" "ᵋ" julia-latexsubs)
+(puthash "\\^g" "ᵍ" julia-latexsubs)
+(puthash "\\^k" "ᵏ" julia-latexsubs)
+(puthash "\\^m" "ᵐ" julia-latexsubs)
+(puthash "\\^o" "ᵒ" julia-latexsubs)
+(puthash "\\^p" "ᵖ" julia-latexsubs)
+(puthash "\\^t" "ᵗ" julia-latexsubs)
+(puthash "\\^u" "ᵘ" julia-latexsubs)
+(puthash "\\^v" "ᵛ" julia-latexsubs)
+(puthash "\\^beta" "ᵝ" julia-latexsubs)
+(puthash "\\^gamma" "ᵞ" julia-latexsubs)
+(puthash "\\^delta" "ᵟ" julia-latexsubs)
+(puthash "\\^phi" "ᵠ" julia-latexsubs)
+(puthash "\\^chi" "ᵡ" julia-latexsubs)
+(puthash "\\_i" "ᵢ" julia-latexsubs)
+(puthash "\\_r" "ᵣ" julia-latexsubs)
+(puthash "\\_u" "ᵤ" julia-latexsubs)
+(puthash "\\_v" "ᵥ" julia-latexsubs)
+(puthash "\\_beta" "ᵦ" julia-latexsubs)
+(puthash "\\_gamma" "ᵧ" julia-latexsubs)
+(puthash "\\_rho" "ᵨ" julia-latexsubs)
+(puthash "\\_phi" "ᵩ" julia-latexsubs)
+(puthash "\\_chi" "ᵪ" julia-latexsubs)
+(puthash "\\^c" "ᶜ" julia-latexsubs)
+(puthash "\\^f" "ᶠ" julia-latexsubs)
+(puthash "\\^iota" "ᶥ" julia-latexsubs)
+(puthash "\\^Phi" "ᶲ" julia-latexsubs)
+(puthash "\\^z" "ᶻ" julia-latexsubs)
+(puthash "\\^theta" "ᶿ" julia-latexsubs)
+(puthash "\\enspace" " " julia-latexsubs)
+(puthash "\\quad" " " julia-latexsubs)
+(puthash "\\thickspace" " " julia-latexsubs)
+(puthash "\\thinspace" " " julia-latexsubs)
+(puthash "\\hspace" " " julia-latexsubs)
+(puthash "\\endash" "–" julia-latexsubs)
+(puthash "\\emdash" "—" julia-latexsubs)
+(puthash "\\Vert" "‖" julia-latexsubs)
+(puthash "\\lq" "‘" julia-latexsubs)
+(puthash "\\rq" "’" julia-latexsubs)
+(puthash "\\reapos" "‛" julia-latexsubs)
+(puthash "\\quotedblleft" "“" julia-latexsubs)
+(puthash "\\quotedblright" "”" julia-latexsubs)
+(puthash "\\dagger" "†" julia-latexsubs)
+(puthash "\\ddagger" "‡" julia-latexsubs)
+(puthash "\\bullet" "•" julia-latexsubs)
+(puthash "\\dots" "…" julia-latexsubs)
+(puthash "\\ldots" "…" julia-latexsubs)
+(puthash "\\perthousand" "‰" julia-latexsubs)
+(puthash "\\pertenthousand" "‱" julia-latexsubs)
+(puthash "\\prime" "′" julia-latexsubs)
+(puthash "\\pprime" "″" julia-latexsubs)
+(puthash "\\ppprime" "‴" julia-latexsubs)
+(puthash "\\backprime" "‵" julia-latexsubs)
+(puthash "\\backpprime" "‶" julia-latexsubs)
+(puthash "\\backppprime" "‷" julia-latexsubs)
+(puthash "\\guilsinglleft" "‹" julia-latexsubs)
+(puthash "\\guilsinglright" "›" julia-latexsubs)
+(puthash "\\:bangbang:" "‼" julia-latexsubs)
+(puthash "\\tieconcat" "⁀" julia-latexsubs)
+(puthash "\\:interrobang:" "⁉" julia-latexsubs)
+(puthash "\\pppprime" "⁗" julia-latexsubs)
+(puthash "\\tricolon" "⁝" julia-latexsubs)
+(puthash "\\nolinebreak" "\u2060" julia-latexsubs)
+(puthash "\\^0" "⁰" julia-latexsubs)
+(puthash "\\^i" "ⁱ" julia-latexsubs)
+(puthash "\\^4" "⁴" julia-latexsubs)
+(puthash "\\^5" "⁵" julia-latexsubs)
+(puthash "\\^6" "⁶" julia-latexsubs)
+(puthash "\\^7" "⁷" julia-latexsubs)
+(puthash "\\^8" "⁸" julia-latexsubs)
+(puthash "\\^9" "⁹" julia-latexsubs)
+(puthash "\\^+" "⁺" julia-latexsubs)
+(puthash "\\^-" "⁻" julia-latexsubs)
+(puthash "\\^=" "⁼" julia-latexsubs)
+(puthash "\\^(" "⁽" julia-latexsubs)
+(puthash "\\^)" "⁾" julia-latexsubs)
+(puthash "\\^n" "ⁿ" julia-latexsubs)
+(puthash "\\_0" "₀" julia-latexsubs)
+(puthash "\\_1" "₁" julia-latexsubs)
+(puthash "\\_2" "₂" julia-latexsubs)
+(puthash "\\_3" "₃" julia-latexsubs)
+(puthash "\\_4" "₄" julia-latexsubs)
+(puthash "\\_5" "₅" julia-latexsubs)
+(puthash "\\_6" "₆" julia-latexsubs)
+(puthash "\\_7" "₇" julia-latexsubs)
+(puthash "\\_8" "₈" julia-latexsubs)
+(puthash "\\_9" "₉" julia-latexsubs)
+(puthash "\\_+" "₊" julia-latexsubs)
+(puthash "\\_-" "₋" julia-latexsubs)
+(puthash "\\_=" "₌" julia-latexsubs)
+(puthash "\\_(" "₍" julia-latexsubs)
+(puthash "\\_)" "₎" julia-latexsubs)
+(puthash "\\_a" "ₐ" julia-latexsubs)
+(puthash "\\_e" "ₑ" julia-latexsubs)
+(puthash "\\_o" "ₒ" julia-latexsubs)
+(puthash "\\_x" "ₓ" julia-latexsubs)
+(puthash "\\_schwa" "ₔ" julia-latexsubs)
+(puthash "\\_h" "ₕ" julia-latexsubs)
+(puthash "\\_k" "ₖ" julia-latexsubs)
+(puthash "\\_l" "ₗ" julia-latexsubs)
+(puthash "\\_m" "ₘ" julia-latexsubs)
+(puthash "\\_n" "ₙ" julia-latexsubs)
+(puthash "\\_p" "ₚ" julia-latexsubs)
+(puthash "\\_s" "ₛ" julia-latexsubs)
+(puthash "\\_t" "ₜ" julia-latexsubs)
+(puthash "\\pes" "₧" julia-latexsubs)
+(puthash "\\euro" "€" julia-latexsubs)
+(puthash "\\leftharpoonaccent" "⃐" julia-latexsubs)
+(puthash "\\rightharpoonaccent" "⃑" julia-latexsubs)
+(puthash "\\vertoverlay" "⃒" julia-latexsubs)
+(puthash "\\overleftarrow" "⃖" julia-latexsubs)
+(puthash "\\vec" "⃗" julia-latexsubs)
+(puthash "\\dddot" "⃛" julia-latexsubs)
+(puthash "\\ddddot" "⃜" julia-latexsubs)
+(puthash "\\enclosecircle" "⃝" julia-latexsubs)
+(puthash "\\enclosesquare" "⃞" julia-latexsubs)
+(puthash "\\enclosediamond" "⃟" julia-latexsubs)
+(puthash "\\overleftrightarrow" "⃡" julia-latexsubs)
+(puthash "\\enclosetriangle" "⃤" julia-latexsubs)
+(puthash "\\annuity" "⃧" julia-latexsubs)
+(puthash "\\threeunderdot" "⃨" julia-latexsubs)
+(puthash "\\widebridgeabove" "⃩" julia-latexsubs)
+(puthash "\\underrightharpoondown" "⃬" julia-latexsubs)
+(puthash "\\underleftharpoondown" "⃭" julia-latexsubs)
+(puthash "\\underleftarrow" "⃮" julia-latexsubs)
+(puthash "\\underrightarrow" "⃯" julia-latexsubs)
+(puthash "\\asteraccent" "⃰" julia-latexsubs)
+(puthash "\\bbC" "ℂ" julia-latexsubs)
+(puthash "\\eulermascheroni" "ℇ" julia-latexsubs)
+(puthash "\\scrg" "ℊ" julia-latexsubs)
+(puthash "\\scrH" "ℋ" julia-latexsubs)
+(puthash "\\frakH" "ℌ" julia-latexsubs)
+(puthash "\\bbH" "ℍ" julia-latexsubs)
+(puthash "\\planck" "ℎ" julia-latexsubs)
+(puthash "\\hslash" "ℏ" julia-latexsubs)
+(puthash "\\scrI" "ℐ" julia-latexsubs)
+(puthash "\\Im" "ℑ" julia-latexsubs)
+(puthash "\\scrL" "ℒ" julia-latexsubs)
+(puthash "\\ell" "ℓ" julia-latexsubs)
+(puthash "\\bbN" "ℕ" julia-latexsubs)
+(puthash "\\numero" "№" julia-latexsubs)
+(puthash "\\wp" "℘" julia-latexsubs)
+(puthash "\\bbP" "ℙ" julia-latexsubs)
+(puthash "\\bbQ" "ℚ" julia-latexsubs)
+(puthash "\\scrR" "ℛ" julia-latexsubs)
+(puthash "\\Re" "ℜ" julia-latexsubs)
+(puthash "\\bbR" "ℝ" julia-latexsubs)
+(puthash "\\xrat" "℞" julia-latexsubs)
+(puthash "\\trademark" "™" julia-latexsubs)
+(puthash "\\:tm:" "™" julia-latexsubs)
+(puthash "\\bbZ" "ℤ" julia-latexsubs)
+(puthash "\\ohm" "Ω" julia-latexsubs)
+(puthash "\\mho" "℧" julia-latexsubs)
+(puthash "\\frakZ" "ℨ" julia-latexsubs)
+(puthash "\\turnediota" "℩" julia-latexsubs)
+(puthash "\\Angstrom" "Å" julia-latexsubs)
+(puthash "\\scrB" "ℬ" julia-latexsubs)
+(puthash "\\frakC" "ℭ" julia-latexsubs)
+(puthash "\\scre" "ℯ" julia-latexsubs)
+(puthash "\\euler" "ℯ" julia-latexsubs)
+(puthash "\\scrE" "ℰ" julia-latexsubs)
+(puthash "\\scrF" "ℱ" julia-latexsubs)
+(puthash "\\Finv" "Ⅎ" julia-latexsubs)
+(puthash "\\scrM" "ℳ" julia-latexsubs)
+(puthash "\\scro" "ℴ" julia-latexsubs)
+(puthash "\\aleph" "ℵ" julia-latexsubs)
+(puthash "\\beth" "ℶ" julia-latexsubs)
+(puthash "\\gimel" "ℷ" julia-latexsubs)
+(puthash "\\daleth" "ℸ" julia-latexsubs)
+(puthash "\\:information_source:" "ℹ" julia-latexsubs)
+(puthash "\\bbpi" "ℼ" julia-latexsubs)
+(puthash "\\bbgamma" "ℽ" julia-latexsubs)
+(puthash "\\bbGamma" "ℾ" julia-latexsubs)
+(puthash "\\bbPi" "ℿ" julia-latexsubs)
+(puthash "\\bbsum" "⅀" julia-latexsubs)
+(puthash "\\Game" "⅁" julia-latexsubs)
+(puthash "\\sansLturned" "⅂" julia-latexsubs)
+(puthash "\\sansLmirrored" "⅃" julia-latexsubs)
+(puthash "\\Yup" "⅄" julia-latexsubs)
+(puthash "\\bbiD" "ⅅ" julia-latexsubs)
+(puthash "\\bbid" "ⅆ" julia-latexsubs)
+(puthash "\\bbie" "ⅇ" julia-latexsubs)
+(puthash "\\bbii" "ⅈ" julia-latexsubs)
+(puthash "\\bbij" "ⅉ" julia-latexsubs)
+(puthash "\\PropertyLine" "⅊" julia-latexsubs)
+(puthash "\\upand" "⅋" julia-latexsubs)
+(puthash "\\1/7" "⅐" julia-latexsubs)
+(puthash "\\1/9" "⅑" julia-latexsubs)
+(puthash "\\1/10" "⅒" julia-latexsubs)
+(puthash "\\1/3" "⅓" julia-latexsubs)
+(puthash "\\2/3" "⅔" julia-latexsubs)
+(puthash "\\1/5" "⅕" julia-latexsubs)
+(puthash "\\2/5" "⅖" julia-latexsubs)
+(puthash "\\3/5" "⅗" julia-latexsubs)
+(puthash "\\4/5" "⅘" julia-latexsubs)
+(puthash "\\1/6" "⅙" julia-latexsubs)
+(puthash "\\5/6" "⅚" julia-latexsubs)
+(puthash "\\1/8" "⅛" julia-latexsubs)
+(puthash "\\3/8" "⅜" julia-latexsubs)
+(puthash "\\5/8" "⅝" julia-latexsubs)
+(puthash "\\7/8" "⅞" julia-latexsubs)
+(puthash "\\1/" "⅟" julia-latexsubs)
+(puthash "\\0/3" "↉" julia-latexsubs)
+(puthash "\\leftarrow" "←" julia-latexsubs)
+(puthash "\\uparrow" "↑" julia-latexsubs)
+(puthash "\\rightarrow" "→" julia-latexsubs)
+(puthash "\\to" "→" julia-latexsubs)
+(puthash "\\downarrow" "↓" julia-latexsubs)
+(puthash "\\:left_right_arrow:" "↔" julia-latexsubs)
+(puthash "\\leftrightarrow" "↔" julia-latexsubs)
+(puthash "\\:arrow_up_down:" "↕" julia-latexsubs)
+(puthash "\\updownarrow" "↕" julia-latexsubs)
+(puthash "\\:arrow_upper_left:" "↖" julia-latexsubs)
+(puthash "\\nwarrow" "↖" julia-latexsubs)
+(puthash "\\nearrow" "↗" julia-latexsubs)
+(puthash "\\:arrow_upper_right:" "↗" julia-latexsubs)
+(puthash "\\:arrow_lower_right:" "↘" julia-latexsubs)
+(puthash "\\searrow" "↘" julia-latexsubs)
+(puthash "\\swarrow" "↙" julia-latexsubs)
+(puthash "\\:arrow_lower_left:" "↙" julia-latexsubs)
+(puthash "\\nleftarrow" "↚" julia-latexsubs)
+(puthash "\\nrightarrow" "↛" julia-latexsubs)
+(puthash "\\leftwavearrow" "↜" julia-latexsubs)
+(puthash "\\rightwavearrow" "↝" julia-latexsubs)
+(puthash "\\twoheadleftarrow" "↞" julia-latexsubs)
+(puthash "\\twoheaduparrow" "↟" julia-latexsubs)
+(puthash "\\twoheadrightarrow" "↠" julia-latexsubs)
+(puthash "\\twoheaddownarrow" "↡" julia-latexsubs)
+(puthash "\\leftarrowtail" "↢" julia-latexsubs)
+(puthash "\\rightarrowtail" "↣" julia-latexsubs)
+(puthash "\\mapsfrom" "↤" julia-latexsubs)
+(puthash "\\mapsup" "↥" julia-latexsubs)
+(puthash "\\mapsto" "↦" julia-latexsubs)
+(puthash "\\mapsdown" "↧" julia-latexsubs)
+(puthash "\\updownarrowbar" "↨" julia-latexsubs)
+(puthash "\\hookleftarrow" "↩" julia-latexsubs)
+(puthash "\\:leftwards_arrow_with_hook:" "↩" julia-latexsubs)
+(puthash "\\:arrow_right_hook:" "↪" julia-latexsubs)
+(puthash "\\hookrightarrow" "↪" julia-latexsubs)
+(puthash "\\looparrowleft" "↫" julia-latexsubs)
+(puthash "\\looparrowright" "↬" julia-latexsubs)
+(puthash "\\leftrightsquigarrow" "↭" julia-latexsubs)
+(puthash "\\nleftrightarrow" "↮" julia-latexsubs)
+(puthash "\\downzigzagarrow" "↯" julia-latexsubs)
+(puthash "\\Lsh" "↰" julia-latexsubs)
+(puthash "\\Rsh" "↱" julia-latexsubs)
+(puthash "\\Ldsh" "↲" julia-latexsubs)
+(puthash "\\Rdsh" "↳" julia-latexsubs)
+(puthash "\\linefeed" "↴" julia-latexsubs)
+(puthash "\\carriagereturn" "↵" julia-latexsubs)
+(puthash "\\curvearrowleft" "↶" julia-latexsubs)
+(puthash "\\curvearrowright" "↷" julia-latexsubs)
+(puthash "\\barovernorthwestarrow" "↸" julia-latexsubs)
+(puthash "\\barleftarrowrightarrowbar" "↹" julia-latexsubs)
+(puthash "\\circlearrowleft" "↺" julia-latexsubs)
+(puthash "\\circlearrowright" "↻" julia-latexsubs)
+(puthash "\\leftharpoonup" "↼" julia-latexsubs)
+(puthash "\\leftharpoondown" "↽" julia-latexsubs)
+(puthash "\\upharpoonright" "↾" julia-latexsubs)
+(puthash "\\upharpoonleft" "↿" julia-latexsubs)
+(puthash "\\rightharpoonup" "⇀" julia-latexsubs)
+(puthash "\\rightharpoondown" "⇁" julia-latexsubs)
+(puthash "\\downharpoonright" "⇂" julia-latexsubs)
+(puthash "\\downharpoonleft" "⇃" julia-latexsubs)
+(puthash "\\rightleftarrows" "⇄" julia-latexsubs)
+(puthash "\\dblarrowupdown" "⇅" julia-latexsubs)
+(puthash "\\leftrightarrows" "⇆" julia-latexsubs)
+(puthash "\\leftleftarrows" "⇇" julia-latexsubs)
+(puthash "\\upuparrows" "⇈" julia-latexsubs)
+(puthash "\\rightrightarrows" "⇉" julia-latexsubs)
+(puthash "\\downdownarrows" "⇊" julia-latexsubs)
+(puthash "\\leftrightharpoons" "⇋" julia-latexsubs)
+(puthash "\\rightleftharpoons" "⇌" julia-latexsubs)
+(puthash "\\nLeftarrow" "⇍" julia-latexsubs)
+(puthash "\\nLeftrightarrow" "⇎" julia-latexsubs)
+(puthash "\\nRightarrow" "⇏" julia-latexsubs)
+(puthash "\\Leftarrow" "⇐" julia-latexsubs)
+(puthash "\\Uparrow" "⇑" julia-latexsubs)
+(puthash "\\Rightarrow" "⇒" julia-latexsubs)
+(puthash "\\Downarrow" "⇓" julia-latexsubs)
+(puthash "\\Leftrightarrow" "⇔" julia-latexsubs)
+(puthash "\\Updownarrow" "⇕" julia-latexsubs)
+(puthash "\\Nwarrow" "⇖" julia-latexsubs)
+(puthash "\\Nearrow" "⇗" julia-latexsubs)
+(puthash "\\Searrow" "⇘" julia-latexsubs)
+(puthash "\\Swarrow" "⇙" julia-latexsubs)
+(puthash "\\Lleftarrow" "⇚" julia-latexsubs)
+(puthash "\\Rrightarrow" "⇛" julia-latexsubs)
+(puthash "\\leftsquigarrow" "⇜" julia-latexsubs)
+(puthash "\\rightsquigarrow" "⇝" julia-latexsubs)
+(puthash "\\nHuparrow" "⇞" julia-latexsubs)
+(puthash "\\nHdownarrow" "⇟" julia-latexsubs)
+(puthash "\\leftdasharrow" "⇠" julia-latexsubs)
+(puthash "\\updasharrow" "⇡" julia-latexsubs)
+(puthash "\\rightdasharrow" "⇢" julia-latexsubs)
+(puthash "\\downdasharrow" "⇣" julia-latexsubs)
+(puthash "\\barleftarrow" "⇤" julia-latexsubs)
+(puthash "\\rightarrowbar" "⇥" julia-latexsubs)
+(puthash "\\leftwhitearrow" "⇦" julia-latexsubs)
+(puthash "\\upwhitearrow" "⇧" julia-latexsubs)
+(puthash "\\rightwhitearrow" "⇨" julia-latexsubs)
+(puthash "\\downwhitearrow" "⇩" julia-latexsubs)
+(puthash "\\whitearrowupfrombar" "⇪" julia-latexsubs)
+(puthash "\\circleonrightarrow" "⇴" julia-latexsubs)
+(puthash "\\DownArrowUpArrow" "⇵" julia-latexsubs)
+(puthash "\\rightthreearrows" "⇶" julia-latexsubs)
+(puthash "\\nvleftarrow" "⇷" julia-latexsubs)
+(puthash "\\nvrightarrow" "⇸" julia-latexsubs)
+(puthash "\\nvleftrightarrow" "⇹" julia-latexsubs)
+(puthash "\\nVleftarrow" "⇺" julia-latexsubs)
+(puthash "\\nVrightarrow" "⇻" julia-latexsubs)
+(puthash "\\nVleftrightarrow" "⇼" julia-latexsubs)
+(puthash "\\leftarrowtriangle" "⇽" julia-latexsubs)
+(puthash "\\rightarrowtriangle" "⇾" julia-latexsubs)
+(puthash "\\leftrightarrowtriangle" "⇿" julia-latexsubs)
+(puthash "\\forall" "∀" julia-latexsubs)
+(puthash "\\complement" "∁" julia-latexsubs)
+(puthash "\\partial" "∂" julia-latexsubs)
+(puthash "\\exists" "∃" julia-latexsubs)
+(puthash "\\nexists" "∄" julia-latexsubs)
+(puthash "\\varnothing" "∅" julia-latexsubs)
+(puthash "\\emptyset" "∅" julia-latexsubs)
+(puthash "\\increment" "∆" julia-latexsubs)
+(puthash "\\del" "∇" julia-latexsubs)
+(puthash "\\nabla" "∇" julia-latexsubs)
+(puthash "\\in" "∈" julia-latexsubs)
+(puthash "\\notin" "∉" julia-latexsubs)
+(puthash "\\smallin" "∊" julia-latexsubs)
+(puthash "\\ni" "∋" julia-latexsubs)
+(puthash "\\nni" "∌" julia-latexsubs)
+(puthash "\\smallni" "∍" julia-latexsubs)
+(puthash "\\QED" "∎" julia-latexsubs)
+(puthash "\\prod" "∏" julia-latexsubs)
+(puthash "\\coprod" "∐" julia-latexsubs)
+(puthash "\\sum" "∑" julia-latexsubs)
+(puthash "\\minus" "−" julia-latexsubs)
+(puthash "\\mp" "∓" julia-latexsubs)
+(puthash "\\dotplus" "∔" julia-latexsubs)
+(puthash "\\setminus" "∖" julia-latexsubs)
+(puthash "\\ast" "∗" julia-latexsubs)
+(puthash "\\circ" "∘" julia-latexsubs)
+(puthash "\\vysmblkcircle" "∙" julia-latexsubs)
+(puthash "\\sqrt" "√" julia-latexsubs)
+(puthash "\\surd" "√" julia-latexsubs)
+(puthash "\\cbrt" "∛" julia-latexsubs)
+(puthash "\\fourthroot" "∜" julia-latexsubs)
+(puthash "\\propto" "∝" julia-latexsubs)
+(puthash "\\infty" "∞" julia-latexsubs)
+(puthash "\\rightangle" "∟" julia-latexsubs)
+(puthash "\\angle" "∠" julia-latexsubs)
+(puthash "\\measuredangle" "∡" julia-latexsubs)
+(puthash "\\sphericalangle" "∢" julia-latexsubs)
+(puthash "\\mid" "∣" julia-latexsubs)
+(puthash "\\nmid" "∤" julia-latexsubs)
+(puthash "\\parallel" "∥" julia-latexsubs)
+(puthash "\\nparallel" "∦" julia-latexsubs)
+(puthash "\\wedge" "∧" julia-latexsubs)
+(puthash "\\vee" "∨" julia-latexsubs)
+(puthash "\\cap" "∩" julia-latexsubs)
+(puthash "\\cup" "∪" julia-latexsubs)
+(puthash "\\int" "∫" julia-latexsubs)
+(puthash "\\iint" "∬" julia-latexsubs)
+(puthash "\\iiint" "∭" julia-latexsubs)
+(puthash "\\oint" "∮" julia-latexsubs)
+(puthash "\\oiint" "∯" julia-latexsubs)
+(puthash "\\oiiint" "∰" julia-latexsubs)
+(puthash "\\clwintegral" "∱" julia-latexsubs)
+(puthash "\\varointclockwise" "∲" julia-latexsubs)
+(puthash "\\ointctrclockwise" "∳" julia-latexsubs)
+(puthash "\\therefore" "∴" julia-latexsubs)
+(puthash "\\because" "∵" julia-latexsubs)
+(puthash "\\Colon" "∷" julia-latexsubs)
+(puthash "\\dotminus" "∸" julia-latexsubs)
+(puthash "\\dotsminusdots" "∺" julia-latexsubs)
+(puthash "\\kernelcontraction" "∻" julia-latexsubs)
+(puthash "\\sim" "∼" julia-latexsubs)
+(puthash "\\backsim" "∽" julia-latexsubs)
+(puthash "\\lazysinv" "∾" julia-latexsubs)
+(puthash "\\sinewave" "∿" julia-latexsubs)
+(puthash "\\wr" "≀" julia-latexsubs)
+(puthash "\\nsim" "≁" julia-latexsubs)
+(puthash "\\eqsim" "≂" julia-latexsubs)
+(puthash "\\neqsim" "≂̸" julia-latexsubs)
+(puthash "\\simeq" "≃" julia-latexsubs)
+(puthash "\\nsime" "≄" julia-latexsubs)
+(puthash "\\cong" "≅" julia-latexsubs)
+(puthash "\\approxnotequal" "≆" julia-latexsubs)
+(puthash "\\ncong" "≇" julia-latexsubs)
+(puthash "\\approx" "≈" julia-latexsubs)
+(puthash "\\napprox" "≉" julia-latexsubs)
+(puthash "\\approxeq" "≊" julia-latexsubs)
+(puthash "\\tildetrpl" "≋" julia-latexsubs)
+(puthash "\\allequal" "≌" julia-latexsubs)
+(puthash "\\asymp" "≍" julia-latexsubs)
+(puthash "\\Bumpeq" "≎" julia-latexsubs)
+(puthash "\\nBumpeq" "≎̸" julia-latexsubs)
+(puthash "\\bumpeq" "≏" julia-latexsubs)
+(puthash "\\nbumpeq" "≏̸" julia-latexsubs)
+(puthash "\\doteq" "≐" julia-latexsubs)
+(puthash "\\Doteq" "≑" julia-latexsubs)
+(puthash "\\fallingdotseq" "≒" julia-latexsubs)
+(puthash "\\risingdotseq" "≓" julia-latexsubs)
+(puthash "\\coloneq" "≔" julia-latexsubs)
+(puthash "\\eqcolon" "≕" julia-latexsubs)
+(puthash "\\eqcirc" "≖" julia-latexsubs)
+(puthash "\\circeq" "≗" julia-latexsubs)
+(puthash "\\arceq" "≘" julia-latexsubs)
+(puthash "\\wedgeq" "≙" julia-latexsubs)
+(puthash "\\veeeq" "≚" julia-latexsubs)
+(puthash "\\starequal" "≛" julia-latexsubs)
+(puthash "\\triangleq" "≜" julia-latexsubs)
+(puthash "\\eqdef" "≝" julia-latexsubs)
+(puthash "\\measeq" "≞" julia-latexsubs)
+(puthash "\\questeq" "≟" julia-latexsubs)
+(puthash "\\ne" "≠" julia-latexsubs)
+(puthash "\\equiv" "≡" julia-latexsubs)
+(puthash "\\nequiv" "≢" julia-latexsubs)
+(puthash "\\Equiv" "≣" julia-latexsubs)
+(puthash "\\le" "≤" julia-latexsubs)
+(puthash "\\leq" "≤" julia-latexsubs)
+(puthash "\\ge" "≥" julia-latexsubs)
+(puthash "\\geq" "≥" julia-latexsubs)
+(puthash "\\leqq" "≦" julia-latexsubs)
+(puthash "\\geqq" "≧" julia-latexsubs)
+(puthash "\\lneqq" "≨" julia-latexsubs)
+(puthash "\\lvertneqq" "≨︀" julia-latexsubs)
+(puthash "\\gneqq" "≩" julia-latexsubs)
+(puthash "\\gvertneqq" "≩︀" julia-latexsubs)
+(puthash "\\ll" "≪" julia-latexsubs)
+(puthash "\\NotLessLess" "≪̸" julia-latexsubs)
+(puthash "\\gg" "≫" julia-latexsubs)
+(puthash "\\NotGreaterGreater" "≫̸" julia-latexsubs)
+(puthash "\\between" "≬" julia-latexsubs)
+(puthash "\\nasymp" "≭" julia-latexsubs)
+(puthash "\\nless" "≮" julia-latexsubs)
+(puthash "\\ngtr" "≯" julia-latexsubs)
+(puthash "\\nleq" "≰" julia-latexsubs)
+(puthash "\\ngeq" "≱" julia-latexsubs)
+(puthash "\\lesssim" "≲" julia-latexsubs)
+(puthash "\\gtrsim" "≳" julia-latexsubs)
+(puthash "\\nlesssim" "≴" julia-latexsubs)
+(puthash "\\ngtrsim" "≵" julia-latexsubs)
+(puthash "\\lessgtr" "≶" julia-latexsubs)
+(puthash "\\gtrless" "≷" julia-latexsubs)
+(puthash "\\notlessgreater" "≸" julia-latexsubs)
+(puthash "\\notgreaterless" "≹" julia-latexsubs)
+(puthash "\\prec" "≺" julia-latexsubs)
+(puthash "\\succ" "≻" julia-latexsubs)
+(puthash "\\preccurlyeq" "≼" julia-latexsubs)
+(puthash "\\succcurlyeq" "≽" julia-latexsubs)
+(puthash "\\precsim" "≾" julia-latexsubs)
+(puthash "\\nprecsim" "≾̸" julia-latexsubs)
+(puthash "\\succsim" "≿" julia-latexsubs)
+(puthash "\\nsuccsim" "≿̸" julia-latexsubs)
+(puthash "\\nprec" "⊀" julia-latexsubs)
+(puthash "\\nsucc" "⊁" julia-latexsubs)
+(puthash "\\subset" "⊂" julia-latexsubs)
+(puthash "\\supset" "⊃" julia-latexsubs)
+(puthash "\\nsubset" "⊄" julia-latexsubs)
+(puthash "\\nsupset" "⊅" julia-latexsubs)
+(puthash "\\subseteq" "⊆" julia-latexsubs)
+(puthash "\\supseteq" "⊇" julia-latexsubs)
+(puthash "\\nsubseteq" "⊈" julia-latexsubs)
+(puthash "\\nsupseteq" "⊉" julia-latexsubs)
+(puthash "\\subsetneq" "⊊" julia-latexsubs)
+(puthash "\\varsubsetneqq" "⊊︀" julia-latexsubs)
+(puthash "\\supsetneq" "⊋" julia-latexsubs)
+(puthash "\\varsupsetneq" "⊋︀" julia-latexsubs)
+(puthash "\\cupdot" "⊍" julia-latexsubs)
+(puthash "\\uplus" "⊎" julia-latexsubs)
+(puthash "\\sqsubset" "⊏" julia-latexsubs)
+(puthash "\\NotSquareSubset" "⊏̸" julia-latexsubs)
+(puthash "\\sqsupset" "⊐" julia-latexsubs)
+(puthash "\\NotSquareSuperset" "⊐̸" julia-latexsubs)
+(puthash "\\sqsubseteq" "⊑" julia-latexsubs)
+(puthash "\\sqsupseteq" "⊒" julia-latexsubs)
+(puthash "\\sqcap" "⊓" julia-latexsubs)
+(puthash "\\sqcup" "⊔" julia-latexsubs)
+(puthash "\\oplus" "⊕" julia-latexsubs)
+(puthash "\\ominus" "⊖" julia-latexsubs)
+(puthash "\\otimes" "⊗" julia-latexsubs)
+(puthash "\\oslash" "⊘" julia-latexsubs)
+(puthash "\\odot" "⊙" julia-latexsubs)
+(puthash "\\circledcirc" "⊚" julia-latexsubs)
+(puthash "\\circledast" "⊛" julia-latexsubs)
+(puthash "\\circledequal" "⊜" julia-latexsubs)
+(puthash "\\circleddash" "⊝" julia-latexsubs)
+(puthash "\\boxplus" "⊞" julia-latexsubs)
+(puthash "\\boxminus" "⊟" julia-latexsubs)
+(puthash "\\boxtimes" "⊠" julia-latexsubs)
+(puthash "\\boxdot" "⊡" julia-latexsubs)
+(puthash "\\vdash" "⊢" julia-latexsubs)
+(puthash "\\dashv" "⊣" julia-latexsubs)
+(puthash "\\top" "⊤" julia-latexsubs)
+(puthash "\\bot" "⊥" julia-latexsubs)
+(puthash "\\models" "⊧" julia-latexsubs)
+(puthash "\\vDash" "⊨" julia-latexsubs)
+(puthash "\\Vdash" "⊩" julia-latexsubs)
+(puthash "\\Vvdash" "⊪" julia-latexsubs)
+(puthash "\\VDash" "⊫" julia-latexsubs)
+(puthash "\\nvdash" "⊬" julia-latexsubs)
+(puthash "\\nvDash" "⊭" julia-latexsubs)
+(puthash "\\nVdash" "⊮" julia-latexsubs)
+(puthash "\\nVDash" "⊯" julia-latexsubs)
+(puthash "\\prurel" "⊰" julia-latexsubs)
+(puthash "\\scurel" "⊱" julia-latexsubs)
+(puthash "\\vartriangleleft" "⊲" julia-latexsubs)
+(puthash "\\vartriangleright" "⊳" julia-latexsubs)
+(puthash "\\trianglelefteq" "⊴" julia-latexsubs)
+(puthash "\\trianglerighteq" "⊵" julia-latexsubs)
+(puthash "\\original" "⊶" julia-latexsubs)
+(puthash "\\image" "⊷" julia-latexsubs)
+(puthash "\\multimap" "⊸" julia-latexsubs)
+(puthash "\\hermitconjmatrix" "⊹" julia-latexsubs)
+(puthash "\\intercal" "⊺" julia-latexsubs)
+(puthash "\\veebar" "⊻" julia-latexsubs)
+(puthash "\\xor" "⊻" julia-latexsubs)
+(puthash "\\barwedge" "⊼" julia-latexsubs)
+(puthash "\\barvee" "⊽" julia-latexsubs)
+(puthash "\\rightanglearc" "⊾" julia-latexsubs)
+(puthash "\\varlrtriangle" "⊿" julia-latexsubs)
+(puthash "\\bigwedge" "⋀" julia-latexsubs)
+(puthash "\\bigvee" "⋁" julia-latexsubs)
+(puthash "\\bigcap" "⋂" julia-latexsubs)
+(puthash "\\bigcup" "⋃" julia-latexsubs)
+(puthash "\\diamond" "⋄" julia-latexsubs)
+(puthash "\\cdot" "⋅" julia-latexsubs)
+(puthash "\\star" "⋆" julia-latexsubs)
+(puthash "\\divideontimes" "⋇" julia-latexsubs)
+(puthash "\\bowtie" "⋈" julia-latexsubs)
+(puthash "\\ltimes" "⋉" julia-latexsubs)
+(puthash "\\rtimes" "⋊" julia-latexsubs)
+(puthash "\\leftthreetimes" "⋋" julia-latexsubs)
+(puthash "\\rightthreetimes" "⋌" julia-latexsubs)
+(puthash "\\backsimeq" "⋍" julia-latexsubs)
+(puthash "\\curlyvee" "⋎" julia-latexsubs)
+(puthash "\\curlywedge" "⋏" julia-latexsubs)
+(puthash "\\Subset" "⋐" julia-latexsubs)
+(puthash "\\Supset" "⋑" julia-latexsubs)
+(puthash "\\Cap" "⋒" julia-latexsubs)
+(puthash "\\Cup" "⋓" julia-latexsubs)
+(puthash "\\pitchfork" "⋔" julia-latexsubs)
+(puthash "\\equalparallel" "⋕" julia-latexsubs)
+(puthash "\\lessdot" "⋖" julia-latexsubs)
+(puthash "\\gtrdot" "⋗" julia-latexsubs)
+(puthash "\\verymuchless" "⋘" julia-latexsubs)
+(puthash "\\ggg" "⋙" julia-latexsubs)
+(puthash "\\lesseqgtr" "⋚" julia-latexsubs)
+(puthash "\\gtreqless" "⋛" julia-latexsubs)
+(puthash "\\eqless" "⋜" julia-latexsubs)
+(puthash "\\eqgtr" "⋝" julia-latexsubs)
+(puthash "\\curlyeqprec" "⋞" julia-latexsubs)
+(puthash "\\curlyeqsucc" "⋟" julia-latexsubs)
+(puthash "\\npreccurlyeq" "⋠" julia-latexsubs)
+(puthash "\\nsucccurlyeq" "⋡" julia-latexsubs)
+(puthash "\\nsqsubseteq" "⋢" julia-latexsubs)
+(puthash "\\nsqsupseteq" "⋣" julia-latexsubs)
+(puthash "\\sqsubsetneq" "⋤" julia-latexsubs)
+(puthash "\\sqspne" "⋥" julia-latexsubs)
+(puthash "\\lnsim" "⋦" julia-latexsubs)
+(puthash "\\gnsim" "⋧" julia-latexsubs)
+(puthash "\\precnsim" "⋨" julia-latexsubs)
+(puthash "\\succnsim" "⋩" julia-latexsubs)
+(puthash "\\ntriangleleft" "⋪" julia-latexsubs)
+(puthash "\\ntriangleright" "⋫" julia-latexsubs)
+(puthash "\\ntrianglelefteq" "⋬" julia-latexsubs)
+(puthash "\\ntrianglerighteq" "⋭" julia-latexsubs)
+(puthash "\\vdots" "⋮" julia-latexsubs)
+(puthash "\\cdots" "⋯" julia-latexsubs)
+(puthash "\\adots" "⋰" julia-latexsubs)
+(puthash "\\ddots" "⋱" julia-latexsubs)
+(puthash "\\disin" "⋲" julia-latexsubs)
+(puthash "\\varisins" "⋳" julia-latexsubs)
+(puthash "\\isins" "⋴" julia-latexsubs)
+(puthash "\\isindot" "⋵" julia-latexsubs)
+(puthash "\\varisinobar" "⋶" julia-latexsubs)
+(puthash "\\isinobar" "⋷" julia-latexsubs)
+(puthash "\\isinvb" "⋸" julia-latexsubs)
+(puthash "\\isinE" "⋹" julia-latexsubs)
+(puthash "\\nisd" "⋺" julia-latexsubs)
+(puthash "\\varnis" "⋻" julia-latexsubs)
+(puthash "\\nis" "⋼" julia-latexsubs)
+(puthash "\\varniobar" "⋽" julia-latexsubs)
+(puthash "\\niobar" "⋾" julia-latexsubs)
+(puthash "\\bagmember" "⋿" julia-latexsubs)
+(puthash "\\diameter" "⌀" julia-latexsubs)
+(puthash "\\house" "⌂" julia-latexsubs)
+(puthash "\\varbarwedge" "⌅" julia-latexsubs)
+(puthash "\\vardoublebarwedge" "⌆" julia-latexsubs)
+(puthash "\\lceil" "⌈" julia-latexsubs)
+(puthash "\\rceil" "⌉" julia-latexsubs)
+(puthash "\\lfloor" "⌊" julia-latexsubs)
+(puthash "\\rfloor" "⌋" julia-latexsubs)
+(puthash "\\invnot" "⌐" julia-latexsubs)
+(puthash "\\sqlozenge" "⌑" julia-latexsubs)
+(puthash "\\profline" "⌒" julia-latexsubs)
+(puthash "\\profsurf" "⌓" julia-latexsubs)
+(puthash "\\recorder" "⌕" julia-latexsubs)
+(puthash "\\viewdata" "⌗" julia-latexsubs)
+(puthash "\\turnednot" "⌙" julia-latexsubs)
+(puthash "\\:watch:" "⌚" julia-latexsubs)
+(puthash "\\:hourglass:" "⌛" julia-latexsubs)
+(puthash "\\ulcorner" "⌜" julia-latexsubs)
+(puthash "\\urcorner" "⌝" julia-latexsubs)
+(puthash "\\llcorner" "⌞" julia-latexsubs)
+(puthash "\\lrcorner" "⌟" julia-latexsubs)
+(puthash "\\frown" "⌢" julia-latexsubs)
+(puthash "\\smile" "⌣" julia-latexsubs)
+(puthash "\\varhexagonlrbonds" "⌬" julia-latexsubs)
+(puthash "\\conictaper" "⌲" julia-latexsubs)
+(puthash "\\topbot" "⌶" julia-latexsubs)
+(puthash "\\obar" "⌽" julia-latexsubs)
+(puthash "\\notslash" "⌿" julia-latexsubs)
+(puthash "\\notbackslash" "⍀" julia-latexsubs)
+(puthash "\\boxupcaret" "⍓" julia-latexsubs)
+(puthash "\\boxquestion" "⍰" julia-latexsubs)
+(puthash "\\hexagon" "⎔" julia-latexsubs)
+(puthash "\\dlcorn" "⎣" julia-latexsubs)
+(puthash "\\lmoustache" "⎰" julia-latexsubs)
+(puthash "\\rmoustache" "⎱" julia-latexsubs)
+(puthash "\\overbracket" "⎴" julia-latexsubs)
+(puthash "\\underbracket" "⎵" julia-latexsubs)
+(puthash "\\bbrktbrk" "⎶" julia-latexsubs)
+(puthash "\\sqrtbottom" "⎷" julia-latexsubs)
+(puthash "\\lvboxline" "⎸" julia-latexsubs)
+(puthash "\\rvboxline" "⎹" julia-latexsubs)
+(puthash "\\varcarriagereturn" "⏎" julia-latexsubs)
+(puthash "\\overbrace" "⏞" julia-latexsubs)
+(puthash "\\underbrace" "⏟" julia-latexsubs)
+(puthash "\\trapezium" "⏢" julia-latexsubs)
+(puthash "\\benzenr" "⏣" julia-latexsubs)
+(puthash "\\strns" "⏤" julia-latexsubs)
+(puthash "\\fltns" "⏥" julia-latexsubs)
+(puthash "\\accurrent" "⏦" julia-latexsubs)
+(puthash "\\elinters" "⏧" julia-latexsubs)
+(puthash "\\:fast_forward:" "⏩" julia-latexsubs)
+(puthash "\\:rewind:" "⏪" julia-latexsubs)
+(puthash "\\:arrow_double_up:" "⏫" julia-latexsubs)
+(puthash "\\:arrow_double_down:" "⏬" julia-latexsubs)
+(puthash "\\:alarm_clock:" "⏰" julia-latexsubs)
+(puthash "\\:hourglass_flowing_sand:" "⏳" julia-latexsubs)
+(puthash "\\blanksymbol" "␢" julia-latexsubs)
+(puthash "\\visiblespace" "␣" julia-latexsubs)
+(puthash "\\:m:" "Ⓜ" julia-latexsubs)
+(puthash "\\circledS" "Ⓢ" julia-latexsubs)
+(puthash "\\dshfnc" "┆" julia-latexsubs)
+(puthash "\\sqfnw" "┙" julia-latexsubs)
+(puthash "\\diagup" "╱" julia-latexsubs)
+(puthash "\\diagdown" "╲" julia-latexsubs)
+(puthash "\\blockuphalf" "▀" julia-latexsubs)
+(puthash "\\blocklowhalf" "▄" julia-latexsubs)
+(puthash "\\blockfull" "█" julia-latexsubs)
+(puthash "\\blocklefthalf" "▌" julia-latexsubs)
+(puthash "\\blockrighthalf" "▐" julia-latexsubs)
+(puthash "\\blockqtrshaded" "░" julia-latexsubs)
+(puthash "\\blockhalfshaded" "▒" julia-latexsubs)
+(puthash "\\blockthreeqtrshaded" "▓" julia-latexsubs)
+(puthash "\\blacksquare" "■" julia-latexsubs)
+(puthash "\\square" "□" julia-latexsubs)
+(puthash "\\squoval" "▢" julia-latexsubs)
+(puthash "\\blackinwhitesquare" "▣" julia-latexsubs)
+(puthash "\\squarehfill" "▤" julia-latexsubs)
+(puthash "\\squarevfill" "▥" julia-latexsubs)
+(puthash "\\squarehvfill" "▦" julia-latexsubs)
+(puthash "\\squarenwsefill" "▧" julia-latexsubs)
+(puthash "\\squareneswfill" "▨" julia-latexsubs)
+(puthash "\\squarecrossfill" "▩" julia-latexsubs)
+(puthash "\\smblksquare" "▪" julia-latexsubs)
+(puthash "\\:black_small_square:" "▪" julia-latexsubs)
+(puthash "\\:white_small_square:" "▫" julia-latexsubs)
+(puthash "\\smwhtsquare" "▫" julia-latexsubs)
+(puthash "\\hrectangleblack" "▬" julia-latexsubs)
+(puthash "\\hrectangle" "▭" julia-latexsubs)
+(puthash "\\vrectangleblack" "▮" julia-latexsubs)
+(puthash "\\vrecto" "▯" julia-latexsubs)
+(puthash "\\parallelogramblack" "▰" julia-latexsubs)
+(puthash "\\parallelogram" "▱" julia-latexsubs)
+(puthash "\\bigblacktriangleup" "▲" julia-latexsubs)
+(puthash "\\bigtriangleup" "△" julia-latexsubs)
+(puthash "\\blacktriangle" "▴" julia-latexsubs)
+(puthash "\\vartriangle" "▵" julia-latexsubs)
+(puthash "\\:arrow_forward:" "▶" julia-latexsubs)
+(puthash "\\blacktriangleright" "▶" julia-latexsubs)
+(puthash "\\triangleright" "▷" julia-latexsubs)
+(puthash "\\smallblacktriangleright" "▸" julia-latexsubs)
+(puthash "\\smalltriangleright" "▹" julia-latexsubs)
+(puthash "\\blackpointerright" "►" julia-latexsubs)
+(puthash "\\whitepointerright" "▻" julia-latexsubs)
+(puthash "\\bigblacktriangledown" "▼" julia-latexsubs)
+(puthash "\\bigtriangledown" "▽" julia-latexsubs)
+(puthash "\\blacktriangledown" "▾" julia-latexsubs)
+(puthash "\\triangledown" "▿" julia-latexsubs)
+(puthash "\\blacktriangleleft" "◀" julia-latexsubs)
+(puthash "\\:arrow_backward:" "◀" julia-latexsubs)
+(puthash "\\triangleleft" "◁" julia-latexsubs)
+(puthash "\\smallblacktriangleleft" "◂" julia-latexsubs)
+(puthash "\\smalltriangleleft" "◃" julia-latexsubs)
+(puthash "\\blackpointerleft" "◄" julia-latexsubs)
+(puthash "\\whitepointerleft" "◅" julia-latexsubs)
+(puthash "\\mdlgblkdiamond" "◆" julia-latexsubs)
+(puthash "\\mdlgwhtdiamond" "◇" julia-latexsubs)
+(puthash "\\blackinwhitediamond" "◈" julia-latexsubs)
+(puthash "\\fisheye" "◉" julia-latexsubs)
+(puthash "\\lozenge" "◊" julia-latexsubs)
+(puthash "\\bigcirc" "○" julia-latexsubs)
+(puthash "\\dottedcircle" "◌" julia-latexsubs)
+(puthash "\\circlevertfill" "◍" julia-latexsubs)
+(puthash "\\bullseye" "◎" julia-latexsubs)
+(puthash "\\mdlgblkcircle" "●" julia-latexsubs)
+(puthash "\\cirfl" "◐" julia-latexsubs)
+(puthash "\\cirfr" "◑" julia-latexsubs)
+(puthash "\\cirfb" "◒" julia-latexsubs)
+(puthash "\\circletophalfblack" "◓" julia-latexsubs)
+(puthash "\\circleurquadblack" "◔" julia-latexsubs)
+(puthash "\\blackcircleulquadwhite" "◕" julia-latexsubs)
+(puthash "\\blacklefthalfcircle" "◖" julia-latexsubs)
+(puthash "\\blackrighthalfcircle" "◗" julia-latexsubs)
+(puthash "\\rvbull" "◘" julia-latexsubs)
+(puthash "\\inversewhitecircle" "◙" julia-latexsubs)
+(puthash "\\invwhiteupperhalfcircle" "◚" julia-latexsubs)
+(puthash "\\invwhitelowerhalfcircle" "◛" julia-latexsubs)
+(puthash "\\ularc" "◜" julia-latexsubs)
+(puthash "\\urarc" "◝" julia-latexsubs)
+(puthash "\\lrarc" "◞" julia-latexsubs)
+(puthash "\\llarc" "◟" julia-latexsubs)
+(puthash "\\topsemicircle" "◠" julia-latexsubs)
+(puthash "\\botsemicircle" "◡" julia-latexsubs)
+(puthash "\\lrblacktriangle" "◢" julia-latexsubs)
+(puthash "\\llblacktriangle" "◣" julia-latexsubs)
+(puthash "\\ulblacktriangle" "◤" julia-latexsubs)
+(puthash "\\urblacktriangle" "◥" julia-latexsubs)
+(puthash "\\smwhtcircle" "◦" julia-latexsubs)
+(puthash "\\sqfl" "◧" julia-latexsubs)
+(puthash "\\sqfr" "◨" julia-latexsubs)
+(puthash "\\squareulblack" "◩" julia-latexsubs)
+(puthash "\\sqfse" "◪" julia-latexsubs)
+(puthash "\\boxbar" "◫" julia-latexsubs)
+(puthash "\\trianglecdot" "◬" julia-latexsubs)
+(puthash "\\triangleleftblack" "◭" julia-latexsubs)
+(puthash "\\trianglerightblack" "◮" julia-latexsubs)
+(puthash "\\lgwhtcircle" "◯" julia-latexsubs)
+(puthash "\\squareulquad" "◰" julia-latexsubs)
+(puthash "\\squarellquad" "◱" julia-latexsubs)
+(puthash "\\squarelrquad" "◲" julia-latexsubs)
+(puthash "\\squareurquad" "◳" julia-latexsubs)
+(puthash "\\circleulquad" "◴" julia-latexsubs)
+(puthash "\\circlellquad" "◵" julia-latexsubs)
+(puthash "\\circlelrquad" "◶" julia-latexsubs)
+(puthash "\\circleurquad" "◷" julia-latexsubs)
+(puthash "\\ultriangle" "◸" julia-latexsubs)
+(puthash "\\urtriangle" "◹" julia-latexsubs)
+(puthash "\\lltriangle" "◺" julia-latexsubs)
+(puthash "\\mdwhtsquare" "◻" julia-latexsubs)
+(puthash "\\:white_medium_square:" "◻" julia-latexsubs)
+(puthash "\\:black_medium_square:" "◼" julia-latexsubs)
+(puthash "\\mdblksquare" "◼" julia-latexsubs)
+(puthash "\\:white_medium_small_square:" "◽" julia-latexsubs)
+(puthash "\\mdsmwhtsquare" "◽" julia-latexsubs)
+(puthash "\\mdsmblksquare" "◾" julia-latexsubs)
+(puthash "\\:black_medium_small_square:" "◾" julia-latexsubs)
+(puthash "\\lrtriangle" "◿" julia-latexsubs)
+(puthash "\\:sunny:" "☀" julia-latexsubs)
+(puthash "\\:cloud:" "☁" julia-latexsubs)
+(puthash "\\bigstar" "★" julia-latexsubs)
+(puthash "\\bigwhitestar" "☆" julia-latexsubs)
+(puthash "\\astrosun" "☉" julia-latexsubs)
+(puthash "\\:phone:" "☎" julia-latexsubs)
+(puthash "\\:ballot_box_with_check:" "☑" julia-latexsubs)
+(puthash "\\:umbrella:" "☔" julia-latexsubs)
+(puthash "\\:coffee:" "☕" julia-latexsubs)
+(puthash "\\:point_up:" "☝" julia-latexsubs)
+(puthash "\\danger" "☡" julia-latexsubs)
+(puthash "\\:relaxed:" "☺" julia-latexsubs)
+(puthash "\\blacksmiley" "☻" julia-latexsubs)
+(puthash "\\sun" "☼" julia-latexsubs)
+(puthash "\\rightmoon" "☽" julia-latexsubs)
+(puthash "\\leftmoon" "☾" julia-latexsubs)
+(puthash "\\mercury" "☿" julia-latexsubs)
+(puthash "\\venus" "♀" julia-latexsubs)
+(puthash "\\female" "♀" julia-latexsubs)
+(puthash "\\male" "♂" julia-latexsubs)
+(puthash "\\mars" "♂" julia-latexsubs)
+(puthash "\\jupiter" "♃" julia-latexsubs)
+(puthash "\\saturn" "♄" julia-latexsubs)
+(puthash "\\uranus" "♅" julia-latexsubs)
+(puthash "\\neptune" "♆" julia-latexsubs)
+(puthash "\\pluto" "♇" julia-latexsubs)
+(puthash "\\:aries:" "♈" julia-latexsubs)
+(puthash "\\aries" "♈" julia-latexsubs)
+(puthash "\\:taurus:" "♉" julia-latexsubs)
+(puthash "\\taurus" "♉" julia-latexsubs)
+(puthash "\\:gemini:" "♊" julia-latexsubs)
+(puthash "\\gemini" "♊" julia-latexsubs)
+(puthash "\\:cancer:" "♋" julia-latexsubs)
+(puthash "\\cancer" "♋" julia-latexsubs)
+(puthash "\\leo" "♌" julia-latexsubs)
+(puthash "\\:leo:" "♌" julia-latexsubs)
+(puthash "\\:virgo:" "♍" julia-latexsubs)
+(puthash "\\virgo" "♍" julia-latexsubs)
+(puthash "\\:libra:" "♎" julia-latexsubs)
+(puthash "\\libra" "♎" julia-latexsubs)
+(puthash "\\scorpio" "♏" julia-latexsubs)
+(puthash "\\:scorpius:" "♏" julia-latexsubs)
+(puthash "\\sagittarius" "♐" julia-latexsubs)
+(puthash "\\:sagittarius:" "♐" julia-latexsubs)
+(puthash "\\capricornus" "♑" julia-latexsubs)
+(puthash "\\:capricorn:" "♑" julia-latexsubs)
+(puthash "\\aquarius" "♒" julia-latexsubs)
+(puthash "\\:aquarius:" "♒" julia-latexsubs)
+(puthash "\\pisces" "♓" julia-latexsubs)
+(puthash "\\:pisces:" "♓" julia-latexsubs)
+(puthash "\\spadesuit" "♠" julia-latexsubs)
+(puthash "\\:spades:" "♠" julia-latexsubs)
+(puthash "\\heartsuit" "♡" julia-latexsubs)
+(puthash "\\diamondsuit" "♢" julia-latexsubs)
+(puthash "\\:clubs:" "♣" julia-latexsubs)
+(puthash "\\clubsuit" "♣" julia-latexsubs)
+(puthash "\\varspadesuit" "♤" julia-latexsubs)
+(puthash "\\varheartsuit" "♥" julia-latexsubs)
+(puthash "\\:hearts:" "♥" julia-latexsubs)
+(puthash "\\vardiamondsuit" "♦" julia-latexsubs)
+(puthash "\\:diamonds:" "♦" julia-latexsubs)
+(puthash "\\varclubsuit" "♧" julia-latexsubs)
+(puthash "\\:hotsprings:" "♨" julia-latexsubs)
+(puthash "\\quarternote" "♩" julia-latexsubs)
+(puthash "\\eighthnote" "♪" julia-latexsubs)
+(puthash "\\twonotes" "♫" julia-latexsubs)
+(puthash "\\flat" "♭" julia-latexsubs)
+(puthash "\\natural" "♮" julia-latexsubs)
+(puthash "\\sharp" "♯" julia-latexsubs)
+(puthash "\\:recycle:" "♻" julia-latexsubs)
+(puthash "\\acidfree" "♾" julia-latexsubs)
+(puthash "\\:wheelchair:" "♿" julia-latexsubs)
+(puthash "\\dicei" "⚀" julia-latexsubs)
+(puthash "\\diceii" "⚁" julia-latexsubs)
+(puthash "\\diceiii" "⚂" julia-latexsubs)
+(puthash "\\diceiv" "⚃" julia-latexsubs)
+(puthash "\\dicev" "⚄" julia-latexsubs)
+(puthash "\\dicevi" "⚅" julia-latexsubs)
+(puthash "\\circledrightdot" "⚆" julia-latexsubs)
+(puthash "\\circledtwodots" "⚇" julia-latexsubs)
+(puthash "\\blackcircledrightdot" "⚈" julia-latexsubs)
+(puthash "\\blackcircledtwodots" "⚉" julia-latexsubs)
+(puthash "\\:anchor:" "⚓" julia-latexsubs)
+(puthash "\\:warning:" "⚠" julia-latexsubs)
+(puthash "\\:zap:" "⚡" julia-latexsubs)
+(puthash "\\hermaphrodite" "⚥" julia-latexsubs)
+(puthash "\\:white_circle:" "⚪" julia-latexsubs)
+(puthash "\\mdwhtcircle" "⚪" julia-latexsubs)
+(puthash "\\mdblkcircle" "⚫" julia-latexsubs)
+(puthash "\\:black_circle:" "⚫" julia-latexsubs)
+(puthash "\\mdsmwhtcircle" "⚬" julia-latexsubs)
+(puthash "\\neuter" "⚲" julia-latexsubs)
+(puthash "\\:soccer:" "⚽" julia-latexsubs)
+(puthash "\\:baseball:" "⚾" julia-latexsubs)
+(puthash "\\:snowman:" "⛄" julia-latexsubs)
+(puthash "\\:partly_sunny:" "⛅" julia-latexsubs)
+(puthash "\\:ophiuchus:" "⛎" julia-latexsubs)
+(puthash "\\:no_entry:" "⛔" julia-latexsubs)
+(puthash "\\:church:" "⛪" julia-latexsubs)
+(puthash "\\:fountain:" "⛲" julia-latexsubs)
+(puthash "\\:golf:" "⛳" julia-latexsubs)
+(puthash "\\:boat:" "⛵" julia-latexsubs)
+(puthash "\\:tent:" "⛺" julia-latexsubs)
+(puthash "\\:fuelpump:" "⛽" julia-latexsubs)
+(puthash "\\:scissors:" "✂" julia-latexsubs)
+(puthash "\\:white_check_mark:" "✅" julia-latexsubs)
+(puthash "\\:airplane:" "✈" julia-latexsubs)
+(puthash "\\:email:" "✉" julia-latexsubs)
+(puthash "\\:fist:" "✊" julia-latexsubs)
+(puthash "\\:hand:" "✋" julia-latexsubs)
+(puthash "\\:v:" "✌" julia-latexsubs)
+(puthash "\\:pencil2:" "✏" julia-latexsubs)
+(puthash "\\:black_nib:" "✒" julia-latexsubs)
+(puthash "\\checkmark" "✓" julia-latexsubs)
+(puthash "\\:heavy_check_mark:" "✔" julia-latexsubs)
+(puthash "\\:heavy_multiplication_x:" "✖" julia-latexsubs)
+(puthash "\\maltese" "✠" julia-latexsubs)
+(puthash "\\:sparkles:" "✨" julia-latexsubs)
+(puthash "\\circledstar" "✪" julia-latexsubs)
+(puthash "\\:eight_spoked_asterisk:" "✳" julia-latexsubs)
+(puthash "\\:eight_pointed_black_star:" "✴" julia-latexsubs)
+(puthash "\\varstar" "✶" julia-latexsubs)
+(puthash "\\dingasterisk" "✽" julia-latexsubs)
+(puthash "\\:snowflake:" "❄" julia-latexsubs)
+(puthash "\\:sparkle:" "❇" julia-latexsubs)
+(puthash "\\:x:" "❌" julia-latexsubs)
+(puthash "\\:negative_squared_cross_mark:" "❎" julia-latexsubs)
+(puthash "\\:question:" "❓" julia-latexsubs)
+(puthash "\\:grey_question:" "❔" julia-latexsubs)
+(puthash "\\:grey_exclamation:" "❕" julia-latexsubs)
+(puthash "\\:exclamation:" "❗" julia-latexsubs)
+(puthash "\\:heart:" "❤" julia-latexsubs)
+(puthash "\\:heavy_plus_sign:" "➕" julia-latexsubs)
+(puthash "\\:heavy_minus_sign:" "➖" julia-latexsubs)
+(puthash "\\:heavy_division_sign:" "➗" julia-latexsubs)
+(puthash "\\draftingarrow" "➛" julia-latexsubs)
+(puthash "\\:arrow_right:" "➡" julia-latexsubs)
+(puthash "\\:curly_loop:" "➰" julia-latexsubs)
+(puthash "\\:loop:" "➿" julia-latexsubs)
+(puthash "\\threedangle" "⟀" julia-latexsubs)
+(puthash "\\whiteinwhitetriangle" "⟁" julia-latexsubs)
+(puthash "\\perp" "⟂" julia-latexsubs)
+(puthash "\\bsolhsub" "⟈" julia-latexsubs)
+(puthash "\\suphsol" "⟉" julia-latexsubs)
+(puthash "\\wedgedot" "⟑" julia-latexsubs)
+(puthash "\\upin" "⟒" julia-latexsubs)
+(puthash "\\leftouterjoin" "⟕" julia-latexsubs)
+(puthash "\\rightouterjoin" "⟖" julia-latexsubs)
+(puthash "\\fullouterjoin" "⟗" julia-latexsubs)
+(puthash "\\bigbot" "⟘" julia-latexsubs)
+(puthash "\\bigtop" "⟙" julia-latexsubs)
+(puthash "\\openbracketleft" "⟦" julia-latexsubs)
+(puthash "\\llbracket" "⟦" julia-latexsubs)
+(puthash "\\openbracketright" "⟧" julia-latexsubs)
+(puthash "\\rrbracket" "⟧" julia-latexsubs)
+(puthash "\\langle" "⟨" julia-latexsubs)
+(puthash "\\rangle" "⟩" julia-latexsubs)
+(puthash "\\UUparrow" "⟰" julia-latexsubs)
+(puthash "\\DDownarrow" "⟱" julia-latexsubs)
+(puthash "\\longleftarrow" "⟵" julia-latexsubs)
+(puthash "\\longrightarrow" "⟶" julia-latexsubs)
+(puthash "\\longleftrightarrow" "⟷" julia-latexsubs)
+(puthash "\\impliedby" "⟸" julia-latexsubs)
+(puthash "\\Longleftarrow" "⟸" julia-latexsubs)
+(puthash "\\implies" "⟹" julia-latexsubs)
+(puthash "\\Longrightarrow" "⟹" julia-latexsubs)
+(puthash "\\iff" "⟺" julia-latexsubs)
+(puthash "\\Longleftrightarrow" "⟺" julia-latexsubs)
+(puthash "\\longmapsfrom" "⟻" julia-latexsubs)
+(puthash "\\longmapsto" "⟼" julia-latexsubs)
+(puthash "\\Longmapsfrom" "⟽" julia-latexsubs)
+(puthash "\\Longmapsto" "⟾" julia-latexsubs)
+(puthash "\\longrightsquigarrow" "⟿" julia-latexsubs)
+(puthash "\\nvtwoheadrightarrow" "⤀" julia-latexsubs)
+(puthash "\\nVtwoheadrightarrow" "⤁" julia-latexsubs)
+(puthash "\\nvLeftarrow" "⤂" julia-latexsubs)
+(puthash "\\nvRightarrow" "⤃" julia-latexsubs)
+(puthash "\\nvLeftrightarrow" "⤄" julia-latexsubs)
+(puthash "\\twoheadmapsto" "⤅" julia-latexsubs)
+(puthash "\\Mapsfrom" "⤆" julia-latexsubs)
+(puthash "\\Mapsto" "⤇" julia-latexsubs)
+(puthash "\\downarrowbarred" "⤈" julia-latexsubs)
+(puthash "\\uparrowbarred" "⤉" julia-latexsubs)
+(puthash "\\Uuparrow" "⤊" julia-latexsubs)
+(puthash "\\Ddownarrow" "⤋" julia-latexsubs)
+(puthash "\\leftbkarrow" "⤌" julia-latexsubs)
+(puthash "\\bkarow" "⤍" julia-latexsubs)
+(puthash "\\leftdbkarrow" "⤎" julia-latexsubs)
+(puthash "\\dbkarow" "⤏" julia-latexsubs)
+(puthash "\\drbkarrow" "⤐" julia-latexsubs)
+(puthash "\\rightdotarrow" "⤑" julia-latexsubs)
+(puthash "\\UpArrowBar" "⤒" julia-latexsubs)
+(puthash "\\DownArrowBar" "⤓" julia-latexsubs)
+(puthash "\\nvrightarrowtail" "⤔" julia-latexsubs)
+(puthash "\\nVrightarrowtail" "⤕" julia-latexsubs)
+(puthash "\\twoheadrightarrowtail" "⤖" julia-latexsubs)
+(puthash "\\nvtwoheadrightarrowtail" "⤗" julia-latexsubs)
+(puthash "\\nVtwoheadrightarrowtail" "⤘" julia-latexsubs)
+(puthash "\\diamondleftarrow" "⤝" julia-latexsubs)
+(puthash "\\rightarrowdiamond" "⤞" julia-latexsubs)
+(puthash "\\diamondleftarrowbar" "⤟" julia-latexsubs)
+(puthash "\\barrightarrowdiamond" "⤠" julia-latexsubs)
+(puthash "\\hksearow" "⤥" julia-latexsubs)
+(puthash "\\hkswarow" "⤦" julia-latexsubs)
+(puthash "\\tona" "⤧" julia-latexsubs)
+(puthash "\\toea" "⤨" julia-latexsubs)
+(puthash "\\tosa" "⤩" julia-latexsubs)
+(puthash "\\towa" "⤪" julia-latexsubs)
+(puthash "\\rdiagovfdiag" "⤫" julia-latexsubs)
+(puthash "\\fdiagovrdiag" "⤬" julia-latexsubs)
+(puthash "\\seovnearrow" "⤭" julia-latexsubs)
+(puthash "\\neovsearrow" "⤮" julia-latexsubs)
+(puthash "\\fdiagovnearrow" "⤯" julia-latexsubs)
+(puthash "\\rdiagovsearrow" "⤰" julia-latexsubs)
+(puthash "\\neovnwarrow" "⤱" julia-latexsubs)
+(puthash "\\nwovnearrow" "⤲" julia-latexsubs)
+(puthash "\\:arrow_heading_up:" "⤴" julia-latexsubs)
+(puthash "\\:arrow_heading_down:" "⤵" julia-latexsubs)
+(puthash "\\Rlarr" "⥂" julia-latexsubs)
+(puthash "\\rLarr" "⥄" julia-latexsubs)
+(puthash "\\rightarrowplus" "⥅" julia-latexsubs)
+(puthash "\\leftarrowplus" "⥆" julia-latexsubs)
+(puthash "\\rarrx" "⥇" julia-latexsubs)
+(puthash "\\leftrightarrowcircle" "⥈" julia-latexsubs)
+(puthash "\\twoheaduparrowcircle" "⥉" julia-latexsubs)
+(puthash "\\leftrightharpoonupdown" "⥊" julia-latexsubs)
+(puthash "\\leftrightharpoondownup" "⥋" julia-latexsubs)
+(puthash "\\updownharpoonrightleft" "⥌" julia-latexsubs)
+(puthash "\\updownharpoonleftright" "⥍" julia-latexsubs)
+(puthash "\\LeftRightVector" "⥎" julia-latexsubs)
+(puthash "\\RightUpDownVector" "⥏" julia-latexsubs)
+(puthash "\\DownLeftRightVector" "⥐" julia-latexsubs)
+(puthash "\\LeftUpDownVector" "⥑" julia-latexsubs)
+(puthash "\\LeftVectorBar" "⥒" julia-latexsubs)
+(puthash "\\RightVectorBar" "⥓" julia-latexsubs)
+(puthash "\\RightUpVectorBar" "⥔" julia-latexsubs)
+(puthash "\\RightDownVectorBar" "⥕" julia-latexsubs)
+(puthash "\\DownLeftVectorBar" "⥖" julia-latexsubs)
+(puthash "\\DownRightVectorBar" "⥗" julia-latexsubs)
+(puthash "\\LeftUpVectorBar" "⥘" julia-latexsubs)
+(puthash "\\LeftDownVectorBar" "⥙" julia-latexsubs)
+(puthash "\\LeftTeeVector" "⥚" julia-latexsubs)
+(puthash "\\RightTeeVector" "⥛" julia-latexsubs)
+(puthash "\\RightUpTeeVector" "⥜" julia-latexsubs)
+(puthash "\\RightDownTeeVector" "⥝" julia-latexsubs)
+(puthash "\\DownLeftTeeVector" "⥞" julia-latexsubs)
+(puthash "\\DownRightTeeVector" "⥟" julia-latexsubs)
+(puthash "\\LeftUpTeeVector" "⥠" julia-latexsubs)
+(puthash "\\LeftDownTeeVector" "⥡" julia-latexsubs)
+(puthash "\\leftharpoonsupdown" "⥢" julia-latexsubs)
+(puthash "\\upharpoonsleftright" "⥣" julia-latexsubs)
+(puthash "\\rightharpoonsupdown" "⥤" julia-latexsubs)
+(puthash "\\downharpoonsleftright" "⥥" julia-latexsubs)
+(puthash "\\leftrightharpoonsup" "⥦" julia-latexsubs)
+(puthash "\\leftrightharpoonsdown" "⥧" julia-latexsubs)
+(puthash "\\rightleftharpoonsup" "⥨" julia-latexsubs)
+(puthash "\\rightleftharpoonsdown" "⥩" julia-latexsubs)
+(puthash "\\leftharpoonupdash" "⥪" julia-latexsubs)
+(puthash "\\dashleftharpoondown" "⥫" julia-latexsubs)
+(puthash "\\rightharpoonupdash" "⥬" julia-latexsubs)
+(puthash "\\dashrightharpoondown" "⥭" julia-latexsubs)
+(puthash "\\UpEquilibrium" "⥮" julia-latexsubs)
+(puthash "\\ReverseUpEquilibrium" "⥯" julia-latexsubs)
+(puthash "\\RoundImplies" "⥰" julia-latexsubs)
+(puthash "\\Vvert" "⦀" julia-latexsubs)
+(puthash "\\Elroang" "⦆" julia-latexsubs)
+(puthash "\\ddfnc" "⦙" julia-latexsubs)
+(puthash "\\measuredangleleft" "⦛" julia-latexsubs)
+(puthash "\\Angle" "⦜" julia-latexsubs)
+(puthash "\\rightanglemdot" "⦝" julia-latexsubs)
+(puthash "\\angles" "⦞" julia-latexsubs)
+(puthash "\\angdnr" "⦟" julia-latexsubs)
+(puthash "\\lpargt" "⦠" julia-latexsubs)
+(puthash "\\sphericalangleup" "⦡" julia-latexsubs)
+(puthash "\\turnangle" "⦢" julia-latexsubs)
+(puthash "\\revangle" "⦣" julia-latexsubs)
+(puthash "\\angleubar" "⦤" julia-latexsubs)
+(puthash "\\revangleubar" "⦥" julia-latexsubs)
+(puthash "\\wideangledown" "⦦" julia-latexsubs)
+(puthash "\\wideangleup" "⦧" julia-latexsubs)
+(puthash "\\measanglerutone" "⦨" julia-latexsubs)
+(puthash "\\measanglelutonw" "⦩" julia-latexsubs)
+(puthash "\\measanglerdtose" "⦪" julia-latexsubs)
+(puthash "\\measangleldtosw" "⦫" julia-latexsubs)
+(puthash "\\measangleurtone" "⦬" julia-latexsubs)
+(puthash "\\measangleultonw" "⦭" julia-latexsubs)
+(puthash "\\measangledrtose" "⦮" julia-latexsubs)
+(puthash "\\measangledltosw" "⦯" julia-latexsubs)
+(puthash "\\revemptyset" "⦰" julia-latexsubs)
+(puthash "\\emptysetobar" "⦱" julia-latexsubs)
+(puthash "\\emptysetocirc" "⦲" julia-latexsubs)
+(puthash "\\emptysetoarr" "⦳" julia-latexsubs)
+(puthash "\\emptysetoarrl" "⦴" julia-latexsubs)
+(puthash "\\circledparallel" "⦷" julia-latexsubs)
+(puthash "\\obslash" "⦸" julia-latexsubs)
+(puthash "\\odotslashdot" "⦼" julia-latexsubs)
+(puthash "\\circledwhitebullet" "⦾" julia-latexsubs)
+(puthash "\\circledbullet" "⦿" julia-latexsubs)
+(puthash "\\olessthan" "⧀" julia-latexsubs)
+(puthash "\\ogreaterthan" "⧁" julia-latexsubs)
+(puthash "\\boxdiag" "⧄" julia-latexsubs)
+(puthash "\\boxbslash" "⧅" julia-latexsubs)
+(puthash "\\boxast" "⧆" julia-latexsubs)
+(puthash "\\boxcircle" "⧇" julia-latexsubs)
+(puthash "\\Lap" "⧊" julia-latexsubs)
+(puthash "\\defas" "⧋" julia-latexsubs)
+(puthash "\\LeftTriangleBar" "⧏" julia-latexsubs)
+(puthash "\\NotLeftTriangleBar" "⧏̸" julia-latexsubs)
+(puthash "\\RightTriangleBar" "⧐" julia-latexsubs)
+(puthash "\\NotRightTriangleBar" "⧐̸" julia-latexsubs)
+(puthash "\\dualmap" "⧟" julia-latexsubs)
+(puthash "\\lrtriangleeq" "⧡" julia-latexsubs)
+(puthash "\\shuffle" "⧢" julia-latexsubs)
+(puthash "\\eparsl" "⧣" julia-latexsubs)
+(puthash "\\smeparsl" "⧤" julia-latexsubs)
+(puthash "\\eqvparsl" "⧥" julia-latexsubs)
+(puthash "\\blacklozenge" "⧫" julia-latexsubs)
+(puthash "\\RuleDelayed" "⧴" julia-latexsubs)
+(puthash "\\dsol" "⧶" julia-latexsubs)
+(puthash "\\rsolbar" "⧷" julia-latexsubs)
+(puthash "\\doubleplus" "⧺" julia-latexsubs)
+(puthash "\\tripleplus" "⧻" julia-latexsubs)
+(puthash "\\bigodot" "⨀" julia-latexsubs)
+(puthash "\\bigoplus" "⨁" julia-latexsubs)
+(puthash "\\bigotimes" "⨂" julia-latexsubs)
+(puthash "\\bigcupdot" "⨃" julia-latexsubs)
+(puthash "\\biguplus" "⨄" julia-latexsubs)
+(puthash "\\bigsqcap" "⨅" julia-latexsubs)
+(puthash "\\bigsqcup" "⨆" julia-latexsubs)
+(puthash "\\conjquant" "⨇" julia-latexsubs)
+(puthash "\\disjquant" "⨈" julia-latexsubs)
+(puthash "\\bigtimes" "⨉" julia-latexsubs)
+(puthash "\\modtwosum" "⨊" julia-latexsubs)
+(puthash "\\sumint" "⨋" julia-latexsubs)
+(puthash "\\iiiint" "⨌" julia-latexsubs)
+(puthash "\\intbar" "⨍" julia-latexsubs)
+(puthash "\\intBar" "⨎" julia-latexsubs)
+(puthash "\\clockoint" "⨏" julia-latexsubs)
+(puthash "\\cirfnint" "⨐" julia-latexsubs)
+(puthash "\\awint" "⨑" julia-latexsubs)
+(puthash "\\rppolint" "⨒" julia-latexsubs)
+(puthash "\\scpolint" "⨓" julia-latexsubs)
+(puthash "\\npolint" "⨔" julia-latexsubs)
+(puthash "\\pointint" "⨕" julia-latexsubs)
+(puthash "\\sqrint" "⨖" julia-latexsubs)
+(puthash "\\intx" "⨘" julia-latexsubs)
+(puthash "\\intcap" "⨙" julia-latexsubs)
+(puthash "\\intcup" "⨚" julia-latexsubs)
+(puthash "\\upint" "⨛" julia-latexsubs)
+(puthash "\\lowint" "⨜" julia-latexsubs)
+(puthash "\\join" "⨝" julia-latexsubs)
+(puthash "\\Join" "⨝" julia-latexsubs)
+(puthash "\\ringplus" "⨢" julia-latexsubs)
+(puthash "\\plushat" "⨣" julia-latexsubs)
+(puthash "\\simplus" "⨤" julia-latexsubs)
+(puthash "\\plusdot" "⨥" julia-latexsubs)
+(puthash "\\plussim" "⨦" julia-latexsubs)
+(puthash "\\plussubtwo" "⨧" julia-latexsubs)
+(puthash "\\plustrif" "⨨" julia-latexsubs)
+(puthash "\\commaminus" "⨩" julia-latexsubs)
+(puthash "\\minusdot" "⨪" julia-latexsubs)
+(puthash "\\minusfdots" "⨫" julia-latexsubs)
+(puthash "\\minusrdots" "⨬" julia-latexsubs)
+(puthash "\\opluslhrim" "⨭" julia-latexsubs)
+(puthash "\\oplusrhrim" "⨮" julia-latexsubs)
+(puthash "\\Times" "⨯" julia-latexsubs)
+(puthash "\\dottimes" "⨰" julia-latexsubs)
+(puthash "\\timesbar" "⨱" julia-latexsubs)
+(puthash "\\btimes" "⨲" julia-latexsubs)
+(puthash "\\smashtimes" "⨳" julia-latexsubs)
+(puthash "\\otimeslhrim" "⨴" julia-latexsubs)
+(puthash "\\otimesrhrim" "⨵" julia-latexsubs)
+(puthash "\\otimeshat" "⨶" julia-latexsubs)
+(puthash "\\Otimes" "⨷" julia-latexsubs)
+(puthash "\\odiv" "⨸" julia-latexsubs)
+(puthash "\\triangleplus" "⨹" julia-latexsubs)
+(puthash "\\triangleminus" "⨺" julia-latexsubs)
+(puthash "\\triangletimes" "⨻" julia-latexsubs)
+(puthash "\\intprod" "⨼" julia-latexsubs)
+(puthash "\\intprodr" "⨽" julia-latexsubs)
+(puthash "\\amalg" "⨿" julia-latexsubs)
+(puthash "\\capdot" "⩀" julia-latexsubs)
+(puthash "\\uminus" "⩁" julia-latexsubs)
+(puthash "\\barcup" "⩂" julia-latexsubs)
+(puthash "\\barcap" "⩃" julia-latexsubs)
+(puthash "\\capwedge" "⩄" julia-latexsubs)
+(puthash "\\cupvee" "⩅" julia-latexsubs)
+(puthash "\\twocups" "⩊" julia-latexsubs)
+(puthash "\\twocaps" "⩋" julia-latexsubs)
+(puthash "\\closedvarcup" "⩌" julia-latexsubs)
+(puthash "\\closedvarcap" "⩍" julia-latexsubs)
+(puthash "\\Sqcap" "⩎" julia-latexsubs)
+(puthash "\\Sqcup" "⩏" julia-latexsubs)
+(puthash "\\closedvarcupsmashprod" "⩐" julia-latexsubs)
+(puthash "\\wedgeodot" "⩑" julia-latexsubs)
+(puthash "\\veeodot" "⩒" julia-latexsubs)
+(puthash "\\And" "⩓" julia-latexsubs)
+(puthash "\\Or" "⩔" julia-latexsubs)
+(puthash "\\wedgeonwedge" "⩕" julia-latexsubs)
+(puthash "\\ElOr" "⩖" julia-latexsubs)
+(puthash "\\bigslopedvee" "⩗" julia-latexsubs)
+(puthash "\\bigslopedwedge" "⩘" julia-latexsubs)
+(puthash "\\wedgemidvert" "⩚" julia-latexsubs)
+(puthash "\\veemidvert" "⩛" julia-latexsubs)
+(puthash "\\midbarwedge" "⩜" julia-latexsubs)
+(puthash "\\midbarvee" "⩝" julia-latexsubs)
+(puthash "\\perspcorrespond" "⩞" julia-latexsubs)
+(puthash "\\minhat" "⩟" julia-latexsubs)
+(puthash "\\wedgedoublebar" "⩠" julia-latexsubs)
+(puthash "\\varveebar" "⩡" julia-latexsubs)
+(puthash "\\doublebarvee" "⩢" julia-latexsubs)
+(puthash "\\veedoublebar" "⩣" julia-latexsubs)
+(puthash "\\eqdot" "⩦" julia-latexsubs)
+(puthash "\\dotequiv" "⩧" julia-latexsubs)
+(puthash "\\dotsim" "⩪" julia-latexsubs)
+(puthash "\\simrdots" "⩫" julia-latexsubs)
+(puthash "\\simminussim" "⩬" julia-latexsubs)
+(puthash "\\congdot" "⩭" julia-latexsubs)
+(puthash "\\asteq" "⩮" julia-latexsubs)
+(puthash "\\hatapprox" "⩯" julia-latexsubs)
+(puthash "\\approxeqq" "⩰" julia-latexsubs)
+(puthash "\\eqqplus" "⩱" julia-latexsubs)
+(puthash "\\pluseqq" "⩲" julia-latexsubs)
+(puthash "\\eqqsim" "⩳" julia-latexsubs)
+(puthash "\\Coloneq" "⩴" julia-latexsubs)
+(puthash "\\Equal" "⩵" julia-latexsubs)
+(puthash "\\eqeqeq" "⩶" julia-latexsubs)
+(puthash "\\ddotseq" "⩷" julia-latexsubs)
+(puthash "\\equivDD" "⩸" julia-latexsubs)
+(puthash "\\ltcir" "⩹" julia-latexsubs)
+(puthash "\\gtcir" "⩺" julia-latexsubs)
+(puthash "\\ltquest" "⩻" julia-latexsubs)
+(puthash "\\gtquest" "⩼" julia-latexsubs)
+(puthash "\\leqslant" "⩽" julia-latexsubs)
+(puthash "\\nleqslant" "⩽̸" julia-latexsubs)
+(puthash "\\geqslant" "⩾" julia-latexsubs)
+(puthash "\\ngeqslant" "⩾̸" julia-latexsubs)
+(puthash "\\lesdot" "⩿" julia-latexsubs)
+(puthash "\\gesdot" "⪀" julia-latexsubs)
+(puthash "\\lesdoto" "⪁" julia-latexsubs)
+(puthash "\\gesdoto" "⪂" julia-latexsubs)
+(puthash "\\lesdotor" "⪃" julia-latexsubs)
+(puthash "\\gesdotol" "⪄" julia-latexsubs)
+(puthash "\\lessapprox" "⪅" julia-latexsubs)
+(puthash "\\gtrapprox" "⪆" julia-latexsubs)
+(puthash "\\lneq" "⪇" julia-latexsubs)
+(puthash "\\gneq" "⪈" julia-latexsubs)
+(puthash "\\lnapprox" "⪉" julia-latexsubs)
+(puthash "\\gnapprox" "⪊" julia-latexsubs)
+(puthash "\\lesseqqgtr" "⪋" julia-latexsubs)
+(puthash "\\gtreqqless" "⪌" julia-latexsubs)
+(puthash "\\lsime" "⪍" julia-latexsubs)
+(puthash "\\gsime" "⪎" julia-latexsubs)
+(puthash "\\lsimg" "⪏" julia-latexsubs)
+(puthash "\\gsiml" "⪐" julia-latexsubs)
+(puthash "\\lgE" "⪑" julia-latexsubs)
+(puthash "\\glE" "⪒" julia-latexsubs)
+(puthash "\\lesges" "⪓" julia-latexsubs)
+(puthash "\\gesles" "⪔" julia-latexsubs)
+(puthash "\\eqslantless" "⪕" julia-latexsubs)
+(puthash "\\eqslantgtr" "⪖" julia-latexsubs)
+(puthash "\\elsdot" "⪗" julia-latexsubs)
+(puthash "\\egsdot" "⪘" julia-latexsubs)
+(puthash "\\eqqless" "⪙" julia-latexsubs)
+(puthash "\\eqqgtr" "⪚" julia-latexsubs)
+(puthash "\\eqqslantless" "⪛" julia-latexsubs)
+(puthash "\\eqqslantgtr" "⪜" julia-latexsubs)
+(puthash "\\simless" "⪝" julia-latexsubs)
+(puthash "\\simgtr" "⪞" julia-latexsubs)
+(puthash "\\simlE" "⪟" julia-latexsubs)
+(puthash "\\simgE" "⪠" julia-latexsubs)
+(puthash "\\NestedLessLess" "⪡" julia-latexsubs)
+(puthash "\\NotNestedLessLess" "⪡̸" julia-latexsubs)
+(puthash "\\NestedGreaterGreater" "⪢" julia-latexsubs)
+(puthash "\\NotNestedGreaterGreater" "⪢̸" julia-latexsubs)
+(puthash "\\partialmeetcontraction" "⪣" julia-latexsubs)
+(puthash "\\glj" "⪤" julia-latexsubs)
+(puthash "\\gla" "⪥" julia-latexsubs)
+(puthash "\\ltcc" "⪦" julia-latexsubs)
+(puthash "\\gtcc" "⪧" julia-latexsubs)
+(puthash "\\lescc" "⪨" julia-latexsubs)
+(puthash "\\gescc" "⪩" julia-latexsubs)
+(puthash "\\smt" "⪪" julia-latexsubs)
+(puthash "\\lat" "⪫" julia-latexsubs)
+(puthash "\\smte" "⪬" julia-latexsubs)
+(puthash "\\late" "⪭" julia-latexsubs)
+(puthash "\\bumpeqq" "⪮" julia-latexsubs)
+(puthash "\\preceq" "⪯" julia-latexsubs)
+(puthash "\\npreceq" "⪯̸" julia-latexsubs)
+(puthash "\\succeq" "⪰" julia-latexsubs)
+(puthash "\\nsucceq" "⪰̸" julia-latexsubs)
+(puthash "\\precneq" "⪱" julia-latexsubs)
+(puthash "\\succneq" "⪲" julia-latexsubs)
+(puthash "\\preceqq" "⪳" julia-latexsubs)
+(puthash "\\succeqq" "⪴" julia-latexsubs)
+(puthash "\\precneqq" "⪵" julia-latexsubs)
+(puthash "\\succneqq" "⪶" julia-latexsubs)
+(puthash "\\precapprox" "⪷" julia-latexsubs)
+(puthash "\\succapprox" "⪸" julia-latexsubs)
+(puthash "\\precnapprox" "⪹" julia-latexsubs)
+(puthash "\\succnapprox" "⪺" julia-latexsubs)
+(puthash "\\Prec" "⪻" julia-latexsubs)
+(puthash "\\Succ" "⪼" julia-latexsubs)
+(puthash "\\subsetdot" "⪽" julia-latexsubs)
+(puthash "\\supsetdot" "⪾" julia-latexsubs)
+(puthash "\\subsetplus" "⪿" julia-latexsubs)
+(puthash "\\supsetplus" "⫀" julia-latexsubs)
+(puthash "\\submult" "⫁" julia-latexsubs)
+(puthash "\\supmult" "⫂" julia-latexsubs)
+(puthash "\\subedot" "⫃" julia-latexsubs)
+(puthash "\\supedot" "⫄" julia-latexsubs)
+(puthash "\\subseteqq" "⫅" julia-latexsubs)
+(puthash "\\nsubseteqq" "⫅̸" julia-latexsubs)
+(puthash "\\supseteqq" "⫆" julia-latexsubs)
+(puthash "\\nsupseteqq" "⫆̸" julia-latexsubs)
+(puthash "\\subsim" "⫇" julia-latexsubs)
+(puthash "\\supsim" "⫈" julia-latexsubs)
+(puthash "\\subsetapprox" "⫉" julia-latexsubs)
+(puthash "\\supsetapprox" "⫊" julia-latexsubs)
+(puthash "\\subsetneqq" "⫋" julia-latexsubs)
+(puthash "\\supsetneqq" "⫌" julia-latexsubs)
+(puthash "\\lsqhook" "⫍" julia-latexsubs)
+(puthash "\\rsqhook" "⫎" julia-latexsubs)
+(puthash "\\csub" "⫏" julia-latexsubs)
+(puthash "\\csup" "⫐" julia-latexsubs)
+(puthash "\\csube" "⫑" julia-latexsubs)
+(puthash "\\csupe" "⫒" julia-latexsubs)
+(puthash "\\subsup" "⫓" julia-latexsubs)
+(puthash "\\supsub" "⫔" julia-latexsubs)
+(puthash "\\subsub" "⫕" julia-latexsubs)
+(puthash "\\supsup" "⫖" julia-latexsubs)
+(puthash "\\suphsub" "⫗" julia-latexsubs)
+(puthash "\\supdsub" "⫘" julia-latexsubs)
+(puthash "\\forkv" "⫙" julia-latexsubs)
+(puthash "\\mlcp" "⫛" julia-latexsubs)
+(puthash "\\forks" "⫝̸" julia-latexsubs)
+(puthash "\\forksnot" "⫝" julia-latexsubs)
+(puthash "\\dashV" "⫣" julia-latexsubs)
+(puthash "\\Dashv" "⫤" julia-latexsubs)
+(puthash "\\interleave" "⫴" julia-latexsubs)
+(puthash "\\tdcol" "⫶" julia-latexsubs)
+(puthash "\\lllnest" "⫷" julia-latexsubs)
+(puthash "\\gggnest" "⫸" julia-latexsubs)
+(puthash "\\leqqslant" "⫹" julia-latexsubs)
+(puthash "\\geqqslant" "⫺" julia-latexsubs)
+(puthash "\\:arrow_left:" "⬅" julia-latexsubs)
+(puthash "\\:arrow_up:" "⬆" julia-latexsubs)
+(puthash "\\:arrow_down:" "⬇" julia-latexsubs)
+(puthash "\\squaretopblack" "⬒" julia-latexsubs)
+(puthash "\\squarebotblack" "⬓" julia-latexsubs)
+(puthash "\\squareurblack" "⬔" julia-latexsubs)
+(puthash "\\squarellblack" "⬕" julia-latexsubs)
+(puthash "\\diamondleftblack" "⬖" julia-latexsubs)
+(puthash "\\diamondrightblack" "⬗" julia-latexsubs)
+(puthash "\\diamondtopblack" "⬘" julia-latexsubs)
+(puthash "\\diamondbotblack" "⬙" julia-latexsubs)
+(puthash "\\dottedsquare" "⬚" julia-latexsubs)
+(puthash "\\lgblksquare" "⬛" julia-latexsubs)
+(puthash "\\:black_large_square:" "⬛" julia-latexsubs)
+(puthash "\\lgwhtsquare" "⬜" julia-latexsubs)
+(puthash "\\:white_large_square:" "⬜" julia-latexsubs)
+(puthash "\\vysmblksquare" "⬝" julia-latexsubs)
+(puthash "\\vysmwhtsquare" "⬞" julia-latexsubs)
+(puthash "\\pentagonblack" "⬟" julia-latexsubs)
+(puthash "\\pentagon" "⬠" julia-latexsubs)
+(puthash "\\varhexagon" "⬡" julia-latexsubs)
+(puthash "\\varhexagonblack" "⬢" julia-latexsubs)
+(puthash "\\hexagonblack" "⬣" julia-latexsubs)
+(puthash "\\lgblkcircle" "⬤" julia-latexsubs)
+(puthash "\\mdblkdiamond" "⬥" julia-latexsubs)
+(puthash "\\mdwhtdiamond" "⬦" julia-latexsubs)
+(puthash "\\mdblklozenge" "⬧" julia-latexsubs)
+(puthash "\\mdwhtlozenge" "⬨" julia-latexsubs)
+(puthash "\\smblkdiamond" "⬩" julia-latexsubs)
+(puthash "\\smblklozenge" "⬪" julia-latexsubs)
+(puthash "\\smwhtlozenge" "⬫" julia-latexsubs)
+(puthash "\\blkhorzoval" "⬬" julia-latexsubs)
+(puthash "\\whthorzoval" "⬭" julia-latexsubs)
+(puthash "\\blkvertoval" "⬮" julia-latexsubs)
+(puthash "\\whtvertoval" "⬯" julia-latexsubs)
+(puthash "\\circleonleftarrow" "⬰" julia-latexsubs)
+(puthash "\\leftthreearrows" "⬱" julia-latexsubs)
+(puthash "\\leftarrowonoplus" "⬲" julia-latexsubs)
+(puthash "\\longleftsquigarrow" "⬳" julia-latexsubs)
+(puthash "\\nvtwoheadleftarrow" "⬴" julia-latexsubs)
+(puthash "\\nVtwoheadleftarrow" "⬵" julia-latexsubs)
+(puthash "\\twoheadmapsfrom" "⬶" julia-latexsubs)
+(puthash "\\twoheadleftdbkarrow" "⬷" julia-latexsubs)
+(puthash "\\leftdotarrow" "⬸" julia-latexsubs)
+(puthash "\\nvleftarrowtail" "⬹" julia-latexsubs)
+(puthash "\\nVleftarrowtail" "⬺" julia-latexsubs)
+(puthash "\\twoheadleftarrowtail" "⬻" julia-latexsubs)
+(puthash "\\nvtwoheadleftarrowtail" "⬼" julia-latexsubs)
+(puthash "\\nVtwoheadleftarrowtail" "⬽" julia-latexsubs)
+(puthash "\\leftarrowx" "⬾" julia-latexsubs)
+(puthash "\\leftcurvedarrow" "⬿" julia-latexsubs)
+(puthash "\\equalleftarrow" "⭀" julia-latexsubs)
+(puthash "\\bsimilarleftarrow" "⭁" julia-latexsubs)
+(puthash "\\leftarrowbackapprox" "⭂" julia-latexsubs)
+(puthash "\\rightarrowgtr" "⭃" julia-latexsubs)
+(puthash "\\rightarrowsupset" "⭄" julia-latexsubs)
+(puthash "\\LLeftarrow" "⭅" julia-latexsubs)
+(puthash "\\RRightarrow" "⭆" julia-latexsubs)
+(puthash "\\bsimilarrightarrow" "⭇" julia-latexsubs)
+(puthash "\\rightarrowbackapprox" "⭈" julia-latexsubs)
+(puthash "\\similarleftarrow" "⭉" julia-latexsubs)
+(puthash "\\leftarrowapprox" "⭊" julia-latexsubs)
+(puthash "\\leftarrowbsimilar" "⭋" julia-latexsubs)
+(puthash "\\rightarrowbsimilar" "⭌" julia-latexsubs)
+(puthash "\\:star:" "⭐" julia-latexsubs)
+(puthash "\\medwhitestar" "⭐" julia-latexsubs)
+(puthash "\\medblackstar" "⭑" julia-latexsubs)
+(puthash "\\smwhitestar" "⭒" julia-latexsubs)
+(puthash "\\rightpentagonblack" "⭓" julia-latexsubs)
+(puthash "\\rightpentagon" "⭔" julia-latexsubs)
+(puthash "\\:o:" "⭕" julia-latexsubs)
+(puthash "\\_j" "ⱼ" julia-latexsubs)
+(puthash "\\^V" "ⱽ" julia-latexsubs)
+(puthash "\\postalmark" "〒" julia-latexsubs)
+(puthash "\\:wavy_dash:" "〰" julia-latexsubs)
+(puthash "\\:part_alternation_mark:" "〽" julia-latexsubs)
+(puthash "\\:congratulations:" "㊗" julia-latexsubs)
+(puthash "\\:secret:" "㊙" julia-latexsubs)
+(puthash "\\bfA" "𝐀" julia-latexsubs)
+(puthash "\\bfB" "𝐁" julia-latexsubs)
+(puthash "\\bfC" "𝐂" julia-latexsubs)
+(puthash "\\bfD" "𝐃" julia-latexsubs)
+(puthash "\\bfE" "𝐄" julia-latexsubs)
+(puthash "\\bfF" "𝐅" julia-latexsubs)
+(puthash "\\bfG" "𝐆" julia-latexsubs)
+(puthash "\\bfH" "𝐇" julia-latexsubs)
+(puthash "\\bfI" "𝐈" julia-latexsubs)
+(puthash "\\bfJ" "𝐉" julia-latexsubs)
+(puthash "\\bfK" "𝐊" julia-latexsubs)
+(puthash "\\bfL" "𝐋" julia-latexsubs)
+(puthash "\\bfM" "𝐌" julia-latexsubs)
+(puthash "\\bfN" "𝐍" julia-latexsubs)
+(puthash "\\bfO" "𝐎" julia-latexsubs)
+(puthash "\\bfP" "𝐏" julia-latexsubs)
+(puthash "\\bfQ" "𝐐" julia-latexsubs)
+(puthash "\\bfR" "𝐑" julia-latexsubs)
+(puthash "\\bfS" "𝐒" julia-latexsubs)
+(puthash "\\bfT" "𝐓" julia-latexsubs)
+(puthash "\\bfU" "𝐔" julia-latexsubs)
+(puthash "\\bfV" "𝐕" julia-latexsubs)
+(puthash "\\bfW" "𝐖" julia-latexsubs)
+(puthash "\\bfX" "𝐗" julia-latexsubs)
+(puthash "\\bfY" "𝐘" julia-latexsubs)
+(puthash "\\bfZ" "𝐙" julia-latexsubs)
+(puthash "\\bfa" "𝐚" julia-latexsubs)
+(puthash "\\bfb" "𝐛" julia-latexsubs)
+(puthash "\\bfc" "𝐜" julia-latexsubs)
+(puthash "\\bfd" "𝐝" julia-latexsubs)
+(puthash "\\bfe" "𝐞" julia-latexsubs)
+(puthash "\\bff" "𝐟" julia-latexsubs)
+(puthash "\\bfg" "𝐠" julia-latexsubs)
+(puthash "\\bfh" "𝐡" julia-latexsubs)
+(puthash "\\bfi" "𝐢" julia-latexsubs)
+(puthash "\\bfj" "𝐣" julia-latexsubs)
+(puthash "\\bfk" "𝐤" julia-latexsubs)
+(puthash "\\bfl" "𝐥" julia-latexsubs)
+(puthash "\\bfm" "𝐦" julia-latexsubs)
+(puthash "\\bfn" "𝐧" julia-latexsubs)
+(puthash "\\bfo" "𝐨" julia-latexsubs)
+(puthash "\\bfp" "𝐩" julia-latexsubs)
+(puthash "\\bfq" "𝐪" julia-latexsubs)
+(puthash "\\bfr" "𝐫" julia-latexsubs)
+(puthash "\\bfs" "𝐬" julia-latexsubs)
+(puthash "\\bft" "𝐭" julia-latexsubs)
+(puthash "\\bfu" "𝐮" julia-latexsubs)
+(puthash "\\bfv" "𝐯" julia-latexsubs)
+(puthash "\\bfw" "𝐰" julia-latexsubs)
+(puthash "\\bfx" "𝐱" julia-latexsubs)
+(puthash "\\bfy" "𝐲" julia-latexsubs)
+(puthash "\\bfz" "𝐳" julia-latexsubs)
+(puthash "\\itA" "𝐴" julia-latexsubs)
+(puthash "\\itB" "𝐵" julia-latexsubs)
+(puthash "\\itC" "𝐶" julia-latexsubs)
+(puthash "\\itD" "𝐷" julia-latexsubs)
+(puthash "\\itE" "𝐸" julia-latexsubs)
+(puthash "\\itF" "𝐹" julia-latexsubs)
+(puthash "\\itG" "𝐺" julia-latexsubs)
+(puthash "\\itH" "𝐻" julia-latexsubs)
+(puthash "\\itI" "𝐼" julia-latexsubs)
+(puthash "\\itJ" "𝐽" julia-latexsubs)
+(puthash "\\itK" "𝐾" julia-latexsubs)
+(puthash "\\itL" "𝐿" julia-latexsubs)
+(puthash "\\itM" "𝑀" julia-latexsubs)
+(puthash "\\itN" "𝑁" julia-latexsubs)
+(puthash "\\itO" "𝑂" julia-latexsubs)
+(puthash "\\itP" "𝑃" julia-latexsubs)
+(puthash "\\itQ" "𝑄" julia-latexsubs)
+(puthash "\\itR" "𝑅" julia-latexsubs)
+(puthash "\\itS" "𝑆" julia-latexsubs)
+(puthash "\\itT" "𝑇" julia-latexsubs)
+(puthash "\\itU" "𝑈" julia-latexsubs)
+(puthash "\\itV" "𝑉" julia-latexsubs)
+(puthash "\\itW" "𝑊" julia-latexsubs)
+(puthash "\\itX" "𝑋" julia-latexsubs)
+(puthash "\\itY" "𝑌" julia-latexsubs)
+(puthash "\\itZ" "𝑍" julia-latexsubs)
+(puthash "\\ita" "𝑎" julia-latexsubs)
+(puthash "\\itb" "𝑏" julia-latexsubs)
+(puthash "\\itc" "𝑐" julia-latexsubs)
+(puthash "\\itd" "𝑑" julia-latexsubs)
+(puthash "\\ite" "𝑒" julia-latexsubs)
+(puthash "\\itf" "𝑓" julia-latexsubs)
+(puthash "\\itg" "𝑔" julia-latexsubs)
+(puthash "\\iti" "𝑖" julia-latexsubs)
+(puthash "\\itj" "𝑗" julia-latexsubs)
+(puthash "\\itk" "𝑘" julia-latexsubs)
+(puthash "\\itl" "𝑙" julia-latexsubs)
+(puthash "\\itm" "𝑚" julia-latexsubs)
+(puthash "\\itn" "𝑛" julia-latexsubs)
+(puthash "\\ito" "𝑜" julia-latexsubs)
+(puthash "\\itp" "𝑝" julia-latexsubs)
+(puthash "\\itq" "𝑞" julia-latexsubs)
+(puthash "\\itr" "𝑟" julia-latexsubs)
+(puthash "\\its" "𝑠" julia-latexsubs)
+(puthash "\\itt" "𝑡" julia-latexsubs)
+(puthash "\\itu" "𝑢" julia-latexsubs)
+(puthash "\\itv" "𝑣" julia-latexsubs)
+(puthash "\\itw" "𝑤" julia-latexsubs)
+(puthash "\\itx" "𝑥" julia-latexsubs)
+(puthash "\\ity" "𝑦" julia-latexsubs)
+(puthash "\\itz" "𝑧" julia-latexsubs)
+(puthash "\\biA" "𝑨" julia-latexsubs)
+(puthash "\\biB" "𝑩" julia-latexsubs)
+(puthash "\\biC" "𝑪" julia-latexsubs)
+(puthash "\\biD" "𝑫" julia-latexsubs)
+(puthash "\\biE" "𝑬" julia-latexsubs)
+(puthash "\\biF" "𝑭" julia-latexsubs)
+(puthash "\\biG" "𝑮" julia-latexsubs)
+(puthash "\\biH" "𝑯" julia-latexsubs)
+(puthash "\\biI" "𝑰" julia-latexsubs)
+(puthash "\\biJ" "𝑱" julia-latexsubs)
+(puthash "\\biK" "𝑲" julia-latexsubs)
+(puthash "\\biL" "𝑳" julia-latexsubs)
+(puthash "\\biM" "𝑴" julia-latexsubs)
+(puthash "\\biN" "𝑵" julia-latexsubs)
+(puthash "\\biO" "𝑶" julia-latexsubs)
+(puthash "\\biP" "𝑷" julia-latexsubs)
+(puthash "\\biQ" "𝑸" julia-latexsubs)
+(puthash "\\biR" "𝑹" julia-latexsubs)
+(puthash "\\biS" "𝑺" julia-latexsubs)
+(puthash "\\biT" "𝑻" julia-latexsubs)
+(puthash "\\biU" "𝑼" julia-latexsubs)
+(puthash "\\biV" "𝑽" julia-latexsubs)
+(puthash "\\biW" "𝑾" julia-latexsubs)
+(puthash "\\biX" "𝑿" julia-latexsubs)
+(puthash "\\biY" "𝒀" julia-latexsubs)
+(puthash "\\biZ" "𝒁" julia-latexsubs)
+(puthash "\\bia" "𝒂" julia-latexsubs)
+(puthash "\\bib" "𝒃" julia-latexsubs)
+(puthash "\\bic" "𝒄" julia-latexsubs)
+(puthash "\\bid" "𝒅" julia-latexsubs)
+(puthash "\\bie" "𝒆" julia-latexsubs)
+(puthash "\\bif" "𝒇" julia-latexsubs)
+(puthash "\\big" "𝒈" julia-latexsubs)
+(puthash "\\bih" "𝒉" julia-latexsubs)
+(puthash "\\bii" "𝒊" julia-latexsubs)
+(puthash "\\bij" "𝒋" julia-latexsubs)
+(puthash "\\bik" "𝒌" julia-latexsubs)
+(puthash "\\bil" "𝒍" julia-latexsubs)
+(puthash "\\bim" "𝒎" julia-latexsubs)
+(puthash "\\bin" "𝒏" julia-latexsubs)
+(puthash "\\bio" "𝒐" julia-latexsubs)
+(puthash "\\bip" "𝒑" julia-latexsubs)
+(puthash "\\biq" "𝒒" julia-latexsubs)
+(puthash "\\bir" "𝒓" julia-latexsubs)
+(puthash "\\bis" "𝒔" julia-latexsubs)
+(puthash "\\bit" "𝒕" julia-latexsubs)
+(puthash "\\biu" "𝒖" julia-latexsubs)
+(puthash "\\biv" "𝒗" julia-latexsubs)
+(puthash "\\biw" "𝒘" julia-latexsubs)
+(puthash "\\bix" "𝒙" julia-latexsubs)
+(puthash "\\biy" "𝒚" julia-latexsubs)
+(puthash "\\biz" "𝒛" julia-latexsubs)
+(puthash "\\scrA" "𝒜" julia-latexsubs)
+(puthash "\\scrC" "𝒞" julia-latexsubs)
+(puthash "\\scrD" "𝒟" julia-latexsubs)
+(puthash "\\scrG" "𝒢" julia-latexsubs)
+(puthash "\\scrJ" "𝒥" julia-latexsubs)
+(puthash "\\scrK" "𝒦" julia-latexsubs)
+(puthash "\\scrN" "𝒩" julia-latexsubs)
+(puthash "\\scrO" "𝒪" julia-latexsubs)
+(puthash "\\scrP" "𝒫" julia-latexsubs)
+(puthash "\\scrQ" "𝒬" julia-latexsubs)
+(puthash "\\scrS" "𝒮" julia-latexsubs)
+(puthash "\\scrT" "𝒯" julia-latexsubs)
+(puthash "\\scrU" "𝒰" julia-latexsubs)
+(puthash "\\scrV" "𝒱" julia-latexsubs)
+(puthash "\\scrW" "𝒲" julia-latexsubs)
+(puthash "\\scrX" "𝒳" julia-latexsubs)
+(puthash "\\scrY" "𝒴" julia-latexsubs)
+(puthash "\\scrZ" "𝒵" julia-latexsubs)
+(puthash "\\scra" "𝒶" julia-latexsubs)
+(puthash "\\scrb" "𝒷" julia-latexsubs)
+(puthash "\\scrc" "𝒸" julia-latexsubs)
+(puthash "\\scrd" "𝒹" julia-latexsubs)
+(puthash "\\scrf" "𝒻" julia-latexsubs)
+(puthash "\\scrh" "𝒽" julia-latexsubs)
+(puthash "\\scri" "𝒾" julia-latexsubs)
+(puthash "\\scrj" "𝒿" julia-latexsubs)
+(puthash "\\scrk" "𝓀" julia-latexsubs)
+(puthash "\\scrl" "𝓁" julia-latexsubs)
+(puthash "\\scrm" "𝓂" julia-latexsubs)
+(puthash "\\scrn" "𝓃" julia-latexsubs)
+(puthash "\\scrp" "𝓅" julia-latexsubs)
+(puthash "\\scrq" "𝓆" julia-latexsubs)
+(puthash "\\scrr" "𝓇" julia-latexsubs)
+(puthash "\\scrs" "𝓈" julia-latexsubs)
+(puthash "\\scrt" "𝓉" julia-latexsubs)
+(puthash "\\scru" "𝓊" julia-latexsubs)
+(puthash "\\scrv" "𝓋" julia-latexsubs)
+(puthash "\\scrw" "𝓌" julia-latexsubs)
+(puthash "\\scrx" "𝓍" julia-latexsubs)
+(puthash "\\scry" "𝓎" julia-latexsubs)
+(puthash "\\scrz" "𝓏" julia-latexsubs)
+(puthash "\\bscrA" "𝓐" julia-latexsubs)
+(puthash "\\bscrB" "𝓑" julia-latexsubs)
+(puthash "\\bscrC" "𝓒" julia-latexsubs)
+(puthash "\\bscrD" "𝓓" julia-latexsubs)
+(puthash "\\bscrE" "𝓔" julia-latexsubs)
+(puthash "\\bscrF" "𝓕" julia-latexsubs)
+(puthash "\\bscrG" "𝓖" julia-latexsubs)
+(puthash "\\bscrH" "𝓗" julia-latexsubs)
+(puthash "\\bscrI" "𝓘" julia-latexsubs)
+(puthash "\\bscrJ" "𝓙" julia-latexsubs)
+(puthash "\\bscrK" "𝓚" julia-latexsubs)
+(puthash "\\bscrL" "𝓛" julia-latexsubs)
+(puthash "\\bscrM" "𝓜" julia-latexsubs)
+(puthash "\\bscrN" "𝓝" julia-latexsubs)
+(puthash "\\bscrO" "𝓞" julia-latexsubs)
+(puthash "\\bscrP" "𝓟" julia-latexsubs)
+(puthash "\\bscrQ" "𝓠" julia-latexsubs)
+(puthash "\\bscrR" "𝓡" julia-latexsubs)
+(puthash "\\bscrS" "𝓢" julia-latexsubs)
+(puthash "\\bscrT" "𝓣" julia-latexsubs)
+(puthash "\\bscrU" "𝓤" julia-latexsubs)
+(puthash "\\bscrV" "𝓥" julia-latexsubs)
+(puthash "\\bscrW" "𝓦" julia-latexsubs)
+(puthash "\\bscrX" "𝓧" julia-latexsubs)
+(puthash "\\bscrY" "𝓨" julia-latexsubs)
+(puthash "\\bscrZ" "𝓩" julia-latexsubs)
+(puthash "\\bscra" "𝓪" julia-latexsubs)
+(puthash "\\bscrb" "𝓫" julia-latexsubs)
+(puthash "\\bscrc" "𝓬" julia-latexsubs)
+(puthash "\\bscrd" "𝓭" julia-latexsubs)
+(puthash "\\bscre" "𝓮" julia-latexsubs)
+(puthash "\\bscrf" "𝓯" julia-latexsubs)
+(puthash "\\bscrg" "𝓰" julia-latexsubs)
+(puthash "\\bscrh" "𝓱" julia-latexsubs)
+(puthash "\\bscri" "𝓲" julia-latexsubs)
+(puthash "\\bscrj" "𝓳" julia-latexsubs)
+(puthash "\\bscrk" "𝓴" julia-latexsubs)
+(puthash "\\bscrl" "𝓵" julia-latexsubs)
+(puthash "\\bscrm" "𝓶" julia-latexsubs)
+(puthash "\\bscrn" "𝓷" julia-latexsubs)
+(puthash "\\bscro" "𝓸" julia-latexsubs)
+(puthash "\\bscrp" "𝓹" julia-latexsubs)
+(puthash "\\bscrq" "𝓺" julia-latexsubs)
+(puthash "\\bscrr" "𝓻" julia-latexsubs)
+(puthash "\\bscrs" "𝓼" julia-latexsubs)
+(puthash "\\bscrt" "𝓽" julia-latexsubs)
+(puthash "\\bscru" "𝓾" julia-latexsubs)
+(puthash "\\bscrv" "𝓿" julia-latexsubs)
+(puthash "\\bscrw" "𝔀" julia-latexsubs)
+(puthash "\\bscrx" "𝔁" julia-latexsubs)
+(puthash "\\bscry" "𝔂" julia-latexsubs)
+(puthash "\\bscrz" "𝔃" julia-latexsubs)
+(puthash "\\frakA" "𝔄" julia-latexsubs)
+(puthash "\\frakB" "𝔅" julia-latexsubs)
+(puthash "\\frakD" "𝔇" julia-latexsubs)
+(puthash "\\frakE" "𝔈" julia-latexsubs)
+(puthash "\\frakF" "𝔉" julia-latexsubs)
+(puthash "\\frakG" "𝔊" julia-latexsubs)
+(puthash "\\frakJ" "𝔍" julia-latexsubs)
+(puthash "\\frakK" "𝔎" julia-latexsubs)
+(puthash "\\frakL" "𝔏" julia-latexsubs)
+(puthash "\\frakM" "𝔐" julia-latexsubs)
+(puthash "\\frakN" "𝔑" julia-latexsubs)
+(puthash "\\frakO" "𝔒" julia-latexsubs)
+(puthash "\\frakP" "𝔓" julia-latexsubs)
+(puthash "\\frakQ" "𝔔" julia-latexsubs)
+(puthash "\\frakS" "𝔖" julia-latexsubs)
+(puthash "\\frakT" "𝔗" julia-latexsubs)
+(puthash "\\frakU" "𝔘" julia-latexsubs)
+(puthash "\\frakV" "𝔙" julia-latexsubs)
+(puthash "\\frakW" "𝔚" julia-latexsubs)
+(puthash "\\frakX" "𝔛" julia-latexsubs)
+(puthash "\\frakY" "𝔜" julia-latexsubs)
+(puthash "\\fraka" "𝔞" julia-latexsubs)
+(puthash "\\frakb" "𝔟" julia-latexsubs)
+(puthash "\\frakc" "𝔠" julia-latexsubs)
+(puthash "\\frakd" "𝔡" julia-latexsubs)
+(puthash "\\frake" "𝔢" julia-latexsubs)
+(puthash "\\frakf" "𝔣" julia-latexsubs)
+(puthash "\\frakg" "𝔤" julia-latexsubs)
+(puthash "\\frakh" "𝔥" julia-latexsubs)
+(puthash "\\fraki" "𝔦" julia-latexsubs)
+(puthash "\\frakj" "𝔧" julia-latexsubs)
+(puthash "\\frakk" "𝔨" julia-latexsubs)
+(puthash "\\frakl" "𝔩" julia-latexsubs)
+(puthash "\\frakm" "𝔪" julia-latexsubs)
+(puthash "\\frakn" "𝔫" julia-latexsubs)
+(puthash "\\frako" "𝔬" julia-latexsubs)
+(puthash "\\frakp" "𝔭" julia-latexsubs)
+(puthash "\\frakq" "𝔮" julia-latexsubs)
+(puthash "\\frakr" "𝔯" julia-latexsubs)
+(puthash "\\fraks" "𝔰" julia-latexsubs)
+(puthash "\\frakt" "𝔱" julia-latexsubs)
+(puthash "\\fraku" "𝔲" julia-latexsubs)
+(puthash "\\frakv" "𝔳" julia-latexsubs)
+(puthash "\\frakw" "𝔴" julia-latexsubs)
+(puthash "\\frakx" "𝔵" julia-latexsubs)
+(puthash "\\fraky" "𝔶" julia-latexsubs)
+(puthash "\\frakz" "𝔷" julia-latexsubs)
+(puthash "\\bbA" "𝔸" julia-latexsubs)
+(puthash "\\bbB" "𝔹" julia-latexsubs)
+(puthash "\\bbD" "𝔻" julia-latexsubs)
+(puthash "\\bbE" "𝔼" julia-latexsubs)
+(puthash "\\bbF" "𝔽" julia-latexsubs)
+(puthash "\\bbG" "𝔾" julia-latexsubs)
+(puthash "\\bbI" "𝕀" julia-latexsubs)
+(puthash "\\bbJ" "𝕁" julia-latexsubs)
+(puthash "\\bbK" "𝕂" julia-latexsubs)
+(puthash "\\bbL" "𝕃" julia-latexsubs)
+(puthash "\\bbM" "𝕄" julia-latexsubs)
+(puthash "\\bbO" "𝕆" julia-latexsubs)
+(puthash "\\bbS" "𝕊" julia-latexsubs)
+(puthash "\\bbT" "𝕋" julia-latexsubs)
+(puthash "\\bbU" "𝕌" julia-latexsubs)
+(puthash "\\bbV" "𝕍" julia-latexsubs)
+(puthash "\\bbW" "𝕎" julia-latexsubs)
+(puthash "\\bbX" "𝕏" julia-latexsubs)
+(puthash "\\bbY" "𝕐" julia-latexsubs)
+(puthash "\\bba" "𝕒" julia-latexsubs)
+(puthash "\\bbb" "𝕓" julia-latexsubs)
+(puthash "\\bbc" "𝕔" julia-latexsubs)
+(puthash "\\bbd" "𝕕" julia-latexsubs)
+(puthash "\\bbe" "𝕖" julia-latexsubs)
+(puthash "\\bbf" "𝕗" julia-latexsubs)
+(puthash "\\bbg" "𝕘" julia-latexsubs)
+(puthash "\\bbh" "𝕙" julia-latexsubs)
+(puthash "\\bbi" "𝕚" julia-latexsubs)
+(puthash "\\bbj" "𝕛" julia-latexsubs)
+(puthash "\\bbk" "𝕜" julia-latexsubs)
+(puthash "\\bbl" "𝕝" julia-latexsubs)
+(puthash "\\bbm" "𝕞" julia-latexsubs)
+(puthash "\\bbn" "𝕟" julia-latexsubs)
+(puthash "\\bbo" "𝕠" julia-latexsubs)
+(puthash "\\bbp" "𝕡" julia-latexsubs)
+(puthash "\\bbq" "𝕢" julia-latexsubs)
+(puthash "\\bbr" "𝕣" julia-latexsubs)
+(puthash "\\bbs" "𝕤" julia-latexsubs)
+(puthash "\\bbt" "𝕥" julia-latexsubs)
+(puthash "\\bbu" "𝕦" julia-latexsubs)
+(puthash "\\bbv" "𝕧" julia-latexsubs)
+(puthash "\\bbw" "𝕨" julia-latexsubs)
+(puthash "\\bbx" "𝕩" julia-latexsubs)
+(puthash "\\bby" "𝕪" julia-latexsubs)
+(puthash "\\bbz" "𝕫" julia-latexsubs)
+(puthash "\\bfrakA" "𝕬" julia-latexsubs)
+(puthash "\\bfrakB" "𝕭" julia-latexsubs)
+(puthash "\\bfrakC" "𝕮" julia-latexsubs)
+(puthash "\\bfrakD" "𝕯" julia-latexsubs)
+(puthash "\\bfrakE" "𝕰" julia-latexsubs)
+(puthash "\\bfrakF" "𝕱" julia-latexsubs)
+(puthash "\\bfrakG" "𝕲" julia-latexsubs)
+(puthash "\\bfrakH" "𝕳" julia-latexsubs)
+(puthash "\\bfrakI" "𝕴" julia-latexsubs)
+(puthash "\\bfrakJ" "𝕵" julia-latexsubs)
+(puthash "\\bfrakK" "𝕶" julia-latexsubs)
+(puthash "\\bfrakL" "𝕷" julia-latexsubs)
+(puthash "\\bfrakM" "𝕸" julia-latexsubs)
+(puthash "\\bfrakN" "𝕹" julia-latexsubs)
+(puthash "\\bfrakO" "𝕺" julia-latexsubs)
+(puthash "\\bfrakP" "𝕻" julia-latexsubs)
+(puthash "\\bfrakQ" "𝕼" julia-latexsubs)
+(puthash "\\bfrakR" "𝕽" julia-latexsubs)
+(puthash "\\bfrakS" "𝕾" julia-latexsubs)
+(puthash "\\bfrakT" "𝕿" julia-latexsubs)
+(puthash "\\bfrakU" "𝖀" julia-latexsubs)
+(puthash "\\bfrakV" "𝖁" julia-latexsubs)
+(puthash "\\bfrakW" "𝖂" julia-latexsubs)
+(puthash "\\bfrakX" "𝖃" julia-latexsubs)
+(puthash "\\bfrakY" "𝖄" julia-latexsubs)
+(puthash "\\bfrakZ" "𝖅" julia-latexsubs)
+(puthash "\\bfraka" "𝖆" julia-latexsubs)
+(puthash "\\bfrakb" "𝖇" julia-latexsubs)
+(puthash "\\bfrakc" "𝖈" julia-latexsubs)
+(puthash "\\bfrakd" "𝖉" julia-latexsubs)
+(puthash "\\bfrake" "𝖊" julia-latexsubs)
+(puthash "\\bfrakf" "𝖋" julia-latexsubs)
+(puthash "\\bfrakg" "𝖌" julia-latexsubs)
+(puthash "\\bfrakh" "𝖍" julia-latexsubs)
+(puthash "\\bfraki" "𝖎" julia-latexsubs)
+(puthash "\\bfrakj" "𝖏" julia-latexsubs)
+(puthash "\\bfrakk" "𝖐" julia-latexsubs)
+(puthash "\\bfrakl" "𝖑" julia-latexsubs)
+(puthash "\\bfrakm" "𝖒" julia-latexsubs)
+(puthash "\\bfrakn" "𝖓" julia-latexsubs)
+(puthash "\\bfrako" "𝖔" julia-latexsubs)
+(puthash "\\bfrakp" "𝖕" julia-latexsubs)
+(puthash "\\bfrakq" "𝖖" julia-latexsubs)
+(puthash "\\bfrakr" "𝖗" julia-latexsubs)
+(puthash "\\bfraks" "𝖘" julia-latexsubs)
+(puthash "\\bfrakt" "𝖙" julia-latexsubs)
+(puthash "\\bfraku" "𝖚" julia-latexsubs)
+(puthash "\\bfrakv" "𝖛" julia-latexsubs)
+(puthash "\\bfrakw" "𝖜" julia-latexsubs)
+(puthash "\\bfrakx" "𝖝" julia-latexsubs)
+(puthash "\\bfraky" "𝖞" julia-latexsubs)
+(puthash "\\bfrakz" "𝖟" julia-latexsubs)
+(puthash "\\sansA" "𝖠" julia-latexsubs)
+(puthash "\\sansB" "𝖡" julia-latexsubs)
+(puthash "\\sansC" "𝖢" julia-latexsubs)
+(puthash "\\sansD" "𝖣" julia-latexsubs)
+(puthash "\\sansE" "𝖤" julia-latexsubs)
+(puthash "\\sansF" "𝖥" julia-latexsubs)
+(puthash "\\sansG" "𝖦" julia-latexsubs)
+(puthash "\\sansH" "𝖧" julia-latexsubs)
+(puthash "\\sansI" "𝖨" julia-latexsubs)
+(puthash "\\sansJ" "𝖩" julia-latexsubs)
+(puthash "\\sansK" "𝖪" julia-latexsubs)
+(puthash "\\sansL" "𝖫" julia-latexsubs)
+(puthash "\\sansM" "𝖬" julia-latexsubs)
+(puthash "\\sansN" "𝖭" julia-latexsubs)
+(puthash "\\sansO" "𝖮" julia-latexsubs)
+(puthash "\\sansP" "𝖯" julia-latexsubs)
+(puthash "\\sansQ" "𝖰" julia-latexsubs)
+(puthash "\\sansR" "𝖱" julia-latexsubs)
+(puthash "\\sansS" "𝖲" julia-latexsubs)
+(puthash "\\sansT" "𝖳" julia-latexsubs)
+(puthash "\\sansU" "𝖴" julia-latexsubs)
+(puthash "\\sansV" "𝖵" julia-latexsubs)
+(puthash "\\sansW" "𝖶" julia-latexsubs)
+(puthash "\\sansX" "𝖷" julia-latexsubs)
+(puthash "\\sansY" "𝖸" julia-latexsubs)
+(puthash "\\sansZ" "𝖹" julia-latexsubs)
+(puthash "\\sansa" "𝖺" julia-latexsubs)
+(puthash "\\sansb" "𝖻" julia-latexsubs)
+(puthash "\\sansc" "𝖼" julia-latexsubs)
+(puthash "\\sansd" "𝖽" julia-latexsubs)
+(puthash "\\sanse" "𝖾" julia-latexsubs)
+(puthash "\\sansf" "𝖿" julia-latexsubs)
+(puthash "\\sansg" "𝗀" julia-latexsubs)
+(puthash "\\sansh" "𝗁" julia-latexsubs)
+(puthash "\\sansi" "𝗂" julia-latexsubs)
+(puthash "\\sansj" "𝗃" julia-latexsubs)
+(puthash "\\sansk" "𝗄" julia-latexsubs)
+(puthash "\\sansl" "𝗅" julia-latexsubs)
+(puthash "\\sansm" "𝗆" julia-latexsubs)
+(puthash "\\sansn" "𝗇" julia-latexsubs)
+(puthash "\\sanso" "𝗈" julia-latexsubs)
+(puthash "\\sansp" "𝗉" julia-latexsubs)
+(puthash "\\sansq" "𝗊" julia-latexsubs)
+(puthash "\\sansr" "𝗋" julia-latexsubs)
+(puthash "\\sanss" "𝗌" julia-latexsubs)
+(puthash "\\sanst" "𝗍" julia-latexsubs)
+(puthash "\\sansu" "𝗎" julia-latexsubs)
+(puthash "\\sansv" "𝗏" julia-latexsubs)
+(puthash "\\sansw" "𝗐" julia-latexsubs)
+(puthash "\\sansx" "𝗑" julia-latexsubs)
+(puthash "\\sansy" "𝗒" julia-latexsubs)
+(puthash "\\sansz" "𝗓" julia-latexsubs)
+(puthash "\\bsansA" "𝗔" julia-latexsubs)
+(puthash "\\bsansB" "𝗕" julia-latexsubs)
+(puthash "\\bsansC" "𝗖" julia-latexsubs)
+(puthash "\\bsansD" "𝗗" julia-latexsubs)
+(puthash "\\bsansE" "𝗘" julia-latexsubs)
+(puthash "\\bsansF" "𝗙" julia-latexsubs)
+(puthash "\\bsansG" "𝗚" julia-latexsubs)
+(puthash "\\bsansH" "𝗛" julia-latexsubs)
+(puthash "\\bsansI" "𝗜" julia-latexsubs)
+(puthash "\\bsansJ" "𝗝" julia-latexsubs)
+(puthash "\\bsansK" "𝗞" julia-latexsubs)
+(puthash "\\bsansL" "𝗟" julia-latexsubs)
+(puthash "\\bsansM" "𝗠" julia-latexsubs)
+(puthash "\\bsansN" "𝗡" julia-latexsubs)
+(puthash "\\bsansO" "𝗢" julia-latexsubs)
+(puthash "\\bsansP" "𝗣" julia-latexsubs)
+(puthash "\\bsansQ" "𝗤" julia-latexsubs)
+(puthash "\\bsansR" "𝗥" julia-latexsubs)
+(puthash "\\bsansS" "𝗦" julia-latexsubs)
+(puthash "\\bsansT" "𝗧" julia-latexsubs)
+(puthash "\\bsansU" "𝗨" julia-latexsubs)
+(puthash "\\bsansV" "𝗩" julia-latexsubs)
+(puthash "\\bsansW" "𝗪" julia-latexsubs)
+(puthash "\\bsansX" "𝗫" julia-latexsubs)
+(puthash "\\bsansY" "𝗬" julia-latexsubs)
+(puthash "\\bsansZ" "𝗭" julia-latexsubs)
+(puthash "\\bsansa" "𝗮" julia-latexsubs)
+(puthash "\\bsansb" "𝗯" julia-latexsubs)
+(puthash "\\bsansc" "𝗰" julia-latexsubs)
+(puthash "\\bsansd" "𝗱" julia-latexsubs)
+(puthash "\\bsanse" "𝗲" julia-latexsubs)
+(puthash "\\bsansf" "𝗳" julia-latexsubs)
+(puthash "\\bsansg" "𝗴" julia-latexsubs)
+(puthash "\\bsansh" "𝗵" julia-latexsubs)
+(puthash "\\bsansi" "𝗶" julia-latexsubs)
+(puthash "\\bsansj" "𝗷" julia-latexsubs)
+(puthash "\\bsansk" "𝗸" julia-latexsubs)
+(puthash "\\bsansl" "𝗹" julia-latexsubs)
+(puthash "\\bsansm" "𝗺" julia-latexsubs)
+(puthash "\\bsansn" "𝗻" julia-latexsubs)
+(puthash "\\bsanso" "𝗼" julia-latexsubs)
+(puthash "\\bsansp" "𝗽" julia-latexsubs)
+(puthash "\\bsansq" "𝗾" julia-latexsubs)
+(puthash "\\bsansr" "𝗿" julia-latexsubs)
+(puthash "\\bsanss" "𝘀" julia-latexsubs)
+(puthash "\\bsanst" "𝘁" julia-latexsubs)
+(puthash "\\bsansu" "𝘂" julia-latexsubs)
+(puthash "\\bsansv" "𝘃" julia-latexsubs)
+(puthash "\\bsansw" "𝘄" julia-latexsubs)
+(puthash "\\bsansx" "𝘅" julia-latexsubs)
+(puthash "\\bsansy" "𝘆" julia-latexsubs)
+(puthash "\\bsansz" "𝘇" julia-latexsubs)
+(puthash "\\isansA" "𝘈" julia-latexsubs)
+(puthash "\\isansB" "𝘉" julia-latexsubs)
+(puthash "\\isansC" "𝘊" julia-latexsubs)
+(puthash "\\isansD" "𝘋" julia-latexsubs)
+(puthash "\\isansE" "𝘌" julia-latexsubs)
+(puthash "\\isansF" "𝘍" julia-latexsubs)
+(puthash "\\isansG" "𝘎" julia-latexsubs)
+(puthash "\\isansH" "𝘏" julia-latexsubs)
+(puthash "\\isansI" "𝘐" julia-latexsubs)
+(puthash "\\isansJ" "𝘑" julia-latexsubs)
+(puthash "\\isansK" "𝘒" julia-latexsubs)
+(puthash "\\isansL" "𝘓" julia-latexsubs)
+(puthash "\\isansM" "𝘔" julia-latexsubs)
+(puthash "\\isansN" "𝘕" julia-latexsubs)
+(puthash "\\isansO" "𝘖" julia-latexsubs)
+(puthash "\\isansP" "𝘗" julia-latexsubs)
+(puthash "\\isansQ" "𝘘" julia-latexsubs)
+(puthash "\\isansR" "𝘙" julia-latexsubs)
+(puthash "\\isansS" "𝘚" julia-latexsubs)
+(puthash "\\isansT" "𝘛" julia-latexsubs)
+(puthash "\\isansU" "𝘜" julia-latexsubs)
+(puthash "\\isansV" "𝘝" julia-latexsubs)
+(puthash "\\isansW" "𝘞" julia-latexsubs)
+(puthash "\\isansX" "𝘟" julia-latexsubs)
+(puthash "\\isansY" "𝘠" julia-latexsubs)
+(puthash "\\isansZ" "𝘡" julia-latexsubs)
+(puthash "\\isansa" "𝘢" julia-latexsubs)
+(puthash "\\isansb" "𝘣" julia-latexsubs)
+(puthash "\\isansc" "𝘤" julia-latexsubs)
+(puthash "\\isansd" "𝘥" julia-latexsubs)
+(puthash "\\isanse" "𝘦" julia-latexsubs)
+(puthash "\\isansf" "𝘧" julia-latexsubs)
+(puthash "\\isansg" "𝘨" julia-latexsubs)
+(puthash "\\isansh" "𝘩" julia-latexsubs)
+(puthash "\\isansi" "𝘪" julia-latexsubs)
+(puthash "\\isansj" "𝘫" julia-latexsubs)
+(puthash "\\isansk" "𝘬" julia-latexsubs)
+(puthash "\\isansl" "𝘭" julia-latexsubs)
+(puthash "\\isansm" "𝘮" julia-latexsubs)
+(puthash "\\isansn" "𝘯" julia-latexsubs)
+(puthash "\\isanso" "𝘰" julia-latexsubs)
+(puthash "\\isansp" "𝘱" julia-latexsubs)
+(puthash "\\isansq" "𝘲" julia-latexsubs)
+(puthash "\\isansr" "𝘳" julia-latexsubs)
+(puthash "\\isanss" "𝘴" julia-latexsubs)
+(puthash "\\isanst" "𝘵" julia-latexsubs)
+(puthash "\\isansu" "𝘶" julia-latexsubs)
+(puthash "\\isansv" "𝘷" julia-latexsubs)
+(puthash "\\isansw" "𝘸" julia-latexsubs)
+(puthash "\\isansx" "𝘹" julia-latexsubs)
+(puthash "\\isansy" "𝘺" julia-latexsubs)
+(puthash "\\isansz" "𝘻" julia-latexsubs)
+(puthash "\\bisansA" "𝘼" julia-latexsubs)
+(puthash "\\bisansB" "𝘽" julia-latexsubs)
+(puthash "\\bisansC" "𝘾" julia-latexsubs)
+(puthash "\\bisansD" "𝘿" julia-latexsubs)
+(puthash "\\bisansE" "𝙀" julia-latexsubs)
+(puthash "\\bisansF" "𝙁" julia-latexsubs)
+(puthash "\\bisansG" "𝙂" julia-latexsubs)
+(puthash "\\bisansH" "𝙃" julia-latexsubs)
+(puthash "\\bisansI" "𝙄" julia-latexsubs)
+(puthash "\\bisansJ" "𝙅" julia-latexsubs)
+(puthash "\\bisansK" "𝙆" julia-latexsubs)
+(puthash "\\bisansL" "𝙇" julia-latexsubs)
+(puthash "\\bisansM" "𝙈" julia-latexsubs)
+(puthash "\\bisansN" "𝙉" julia-latexsubs)
+(puthash "\\bisansO" "𝙊" julia-latexsubs)
+(puthash "\\bisansP" "𝙋" julia-latexsubs)
+(puthash "\\bisansQ" "𝙌" julia-latexsubs)
+(puthash "\\bisansR" "𝙍" julia-latexsubs)
+(puthash "\\bisansS" "𝙎" julia-latexsubs)
+(puthash "\\bisansT" "𝙏" julia-latexsubs)
+(puthash "\\bisansU" "𝙐" julia-latexsubs)
+(puthash "\\bisansV" "𝙑" julia-latexsubs)
+(puthash "\\bisansW" "𝙒" julia-latexsubs)
+(puthash "\\bisansX" "𝙓" julia-latexsubs)
+(puthash "\\bisansY" "𝙔" julia-latexsubs)
+(puthash "\\bisansZ" "𝙕" julia-latexsubs)
+(puthash "\\bisansa" "𝙖" julia-latexsubs)
+(puthash "\\bisansb" "𝙗" julia-latexsubs)
+(puthash "\\bisansc" "𝙘" julia-latexsubs)
+(puthash "\\bisansd" "𝙙" julia-latexsubs)
+(puthash "\\bisanse" "𝙚" julia-latexsubs)
+(puthash "\\bisansf" "𝙛" julia-latexsubs)
+(puthash "\\bisansg" "𝙜" julia-latexsubs)
+(puthash "\\bisansh" "𝙝" julia-latexsubs)
+(puthash "\\bisansi" "𝙞" julia-latexsubs)
+(puthash "\\bisansj" "𝙟" julia-latexsubs)
+(puthash "\\bisansk" "𝙠" julia-latexsubs)
+(puthash "\\bisansl" "𝙡" julia-latexsubs)
+(puthash "\\bisansm" "𝙢" julia-latexsubs)
+(puthash "\\bisansn" "𝙣" julia-latexsubs)
+(puthash "\\bisanso" "𝙤" julia-latexsubs)
+(puthash "\\bisansp" "𝙥" julia-latexsubs)
+(puthash "\\bisansq" "𝙦" julia-latexsubs)
+(puthash "\\bisansr" "𝙧" julia-latexsubs)
+(puthash "\\bisanss" "𝙨" julia-latexsubs)
+(puthash "\\bisanst" "𝙩" julia-latexsubs)
+(puthash "\\bisansu" "𝙪" julia-latexsubs)
+(puthash "\\bisansv" "𝙫" julia-latexsubs)
+(puthash "\\bisansw" "𝙬" julia-latexsubs)
+(puthash "\\bisansx" "𝙭" julia-latexsubs)
+(puthash "\\bisansy" "𝙮" julia-latexsubs)
+(puthash "\\bisansz" "𝙯" julia-latexsubs)
+(puthash "\\ttA" "𝙰" julia-latexsubs)
+(puthash "\\ttB" "𝙱" julia-latexsubs)
+(puthash "\\ttC" "𝙲" julia-latexsubs)
+(puthash "\\ttD" "𝙳" julia-latexsubs)
+(puthash "\\ttE" "𝙴" julia-latexsubs)
+(puthash "\\ttF" "𝙵" julia-latexsubs)
+(puthash "\\ttG" "𝙶" julia-latexsubs)
+(puthash "\\ttH" "𝙷" julia-latexsubs)
+(puthash "\\ttI" "𝙸" julia-latexsubs)
+(puthash "\\ttJ" "𝙹" julia-latexsubs)
+(puthash "\\ttK" "𝙺" julia-latexsubs)
+(puthash "\\ttL" "𝙻" julia-latexsubs)
+(puthash "\\ttM" "𝙼" julia-latexsubs)
+(puthash "\\ttN" "𝙽" julia-latexsubs)
+(puthash "\\ttO" "𝙾" julia-latexsubs)
+(puthash "\\ttP" "𝙿" julia-latexsubs)
+(puthash "\\ttQ" "𝚀" julia-latexsubs)
+(puthash "\\ttR" "𝚁" julia-latexsubs)
+(puthash "\\ttS" "𝚂" julia-latexsubs)
+(puthash "\\ttT" "𝚃" julia-latexsubs)
+(puthash "\\ttU" "𝚄" julia-latexsubs)
+(puthash "\\ttV" "𝚅" julia-latexsubs)
+(puthash "\\ttW" "𝚆" julia-latexsubs)
+(puthash "\\ttX" "𝚇" julia-latexsubs)
+(puthash "\\ttY" "𝚈" julia-latexsubs)
+(puthash "\\ttZ" "𝚉" julia-latexsubs)
+(puthash "\\tta" "𝚊" julia-latexsubs)
+(puthash "\\ttb" "𝚋" julia-latexsubs)
+(puthash "\\ttc" "𝚌" julia-latexsubs)
+(puthash "\\ttd" "𝚍" julia-latexsubs)
+(puthash "\\tte" "𝚎" julia-latexsubs)
+(puthash "\\ttf" "𝚏" julia-latexsubs)
+(puthash "\\ttg" "𝚐" julia-latexsubs)
+(puthash "\\tth" "𝚑" julia-latexsubs)
+(puthash "\\tti" "𝚒" julia-latexsubs)
+(puthash "\\ttj" "𝚓" julia-latexsubs)
+(puthash "\\ttk" "𝚔" julia-latexsubs)
+(puthash "\\ttl" "𝚕" julia-latexsubs)
+(puthash "\\ttm" "𝚖" julia-latexsubs)
+(puthash "\\ttn" "𝚗" julia-latexsubs)
+(puthash "\\tto" "𝚘" julia-latexsubs)
+(puthash "\\ttp" "𝚙" julia-latexsubs)
+(puthash "\\ttq" "𝚚" julia-latexsubs)
+(puthash "\\ttr" "𝚛" julia-latexsubs)
+(puthash "\\tts" "𝚜" julia-latexsubs)
+(puthash "\\ttt" "𝚝" julia-latexsubs)
+(puthash "\\ttu" "𝚞" julia-latexsubs)
+(puthash "\\ttv" "𝚟" julia-latexsubs)
+(puthash "\\ttw" "𝚠" julia-latexsubs)
+(puthash "\\ttx" "𝚡" julia-latexsubs)
+(puthash "\\tty" "𝚢" julia-latexsubs)
+(puthash "\\ttz" "𝚣" julia-latexsubs)
+(puthash "\\itimath" "𝚤" julia-latexsubs)
+(puthash "\\itjmath" "𝚥" julia-latexsubs)
+(puthash "\\bfAlpha" "𝚨" julia-latexsubs)
+(puthash "\\bfBeta" "𝚩" julia-latexsubs)
+(puthash "\\bfGamma" "𝚪" julia-latexsubs)
+(puthash "\\bfDelta" "𝚫" julia-latexsubs)
+(puthash "\\bfEpsilon" "𝚬" julia-latexsubs)
+(puthash "\\bfZeta" "𝚭" julia-latexsubs)
+(puthash "\\bfEta" "𝚮" julia-latexsubs)
+(puthash "\\bfTheta" "𝚯" julia-latexsubs)
+(puthash "\\bfIota" "𝚰" julia-latexsubs)
+(puthash "\\bfKappa" "𝚱" julia-latexsubs)
+(puthash "\\bfLambda" "𝚲" julia-latexsubs)
+(puthash "\\bfMu" "𝚳" julia-latexsubs)
+(puthash "\\bfNu" "𝚴" julia-latexsubs)
+(puthash "\\bfXi" "𝚵" julia-latexsubs)
+(puthash "\\bfOmicron" "𝚶" julia-latexsubs)
+(puthash "\\bfPi" "𝚷" julia-latexsubs)
+(puthash "\\bfRho" "𝚸" julia-latexsubs)
+(puthash "\\bfvarTheta" "𝚹" julia-latexsubs)
+(puthash "\\bfSigma" "𝚺" julia-latexsubs)
+(puthash "\\bfTau" "𝚻" julia-latexsubs)
+(puthash "\\bfUpsilon" "𝚼" julia-latexsubs)
+(puthash "\\bfPhi" "𝚽" julia-latexsubs)
+(puthash "\\bfChi" "𝚾" julia-latexsubs)
+(puthash "\\bfPsi" "𝚿" julia-latexsubs)
+(puthash "\\bfOmega" "𝛀" julia-latexsubs)
+(puthash "\\bfnabla" "𝛁" julia-latexsubs)
+(puthash "\\bfalpha" "𝛂" julia-latexsubs)
+(puthash "\\bfbeta" "𝛃" julia-latexsubs)
+(puthash "\\bfgamma" "𝛄" julia-latexsubs)
+(puthash "\\bfdelta" "𝛅" julia-latexsubs)
+(puthash "\\bfepsilon" "𝛆" julia-latexsubs)
+(puthash "\\bfzeta" "𝛇" julia-latexsubs)
+(puthash "\\bfeta" "𝛈" julia-latexsubs)
+(puthash "\\bftheta" "𝛉" julia-latexsubs)
+(puthash "\\bfiota" "𝛊" julia-latexsubs)
+(puthash "\\bfkappa" "𝛋" julia-latexsubs)
+(puthash "\\bflambda" "𝛌" julia-latexsubs)
+(puthash "\\bfmu" "𝛍" julia-latexsubs)
+(puthash "\\bfnu" "𝛎" julia-latexsubs)
+(puthash "\\bfxi" "𝛏" julia-latexsubs)
+(puthash "\\bfomicron" "𝛐" julia-latexsubs)
+(puthash "\\bfpi" "𝛑" julia-latexsubs)
+(puthash "\\bfrho" "𝛒" julia-latexsubs)
+(puthash "\\bfvarsigma" "𝛓" julia-latexsubs)
+(puthash "\\bfsigma" "𝛔" julia-latexsubs)
+(puthash "\\bftau" "𝛕" julia-latexsubs)
+(puthash "\\bfupsilon" "𝛖" julia-latexsubs)
+(puthash "\\bfvarphi" "𝛗" julia-latexsubs)
+(puthash "\\bfchi" "𝛘" julia-latexsubs)
+(puthash "\\bfpsi" "𝛙" julia-latexsubs)
+(puthash "\\bfomega" "𝛚" julia-latexsubs)
+(puthash "\\bfpartial" "𝛛" julia-latexsubs)
+(puthash "\\bfvarepsilon" "𝛜" julia-latexsubs)
+(puthash "\\bfvartheta" "𝛝" julia-latexsubs)
+(puthash "\\bfvarkappa" "𝛞" julia-latexsubs)
+(puthash "\\bfphi" "𝛟" julia-latexsubs)
+(puthash "\\bfvarrho" "𝛠" julia-latexsubs)
+(puthash "\\bfvarpi" "𝛡" julia-latexsubs)
+(puthash "\\itAlpha" "𝛢" julia-latexsubs)
+(puthash "\\itBeta" "𝛣" julia-latexsubs)
+(puthash "\\itGamma" "𝛤" julia-latexsubs)
+(puthash "\\itDelta" "𝛥" julia-latexsubs)
+(puthash "\\itEpsilon" "𝛦" julia-latexsubs)
+(puthash "\\itZeta" "𝛧" julia-latexsubs)
+(puthash "\\itEta" "𝛨" julia-latexsubs)
+(puthash "\\itTheta" "𝛩" julia-latexsubs)
+(puthash "\\itIota" "𝛪" julia-latexsubs)
+(puthash "\\itKappa" "𝛫" julia-latexsubs)
+(puthash "\\itLambda" "𝛬" julia-latexsubs)
+(puthash "\\itMu" "𝛭" julia-latexsubs)
+(puthash "\\itNu" "𝛮" julia-latexsubs)
+(puthash "\\itXi" "𝛯" julia-latexsubs)
+(puthash "\\itOmicron" "𝛰" julia-latexsubs)
+(puthash "\\itPi" "𝛱" julia-latexsubs)
+(puthash "\\itRho" "𝛲" julia-latexsubs)
+(puthash "\\itvarTheta" "𝛳" julia-latexsubs)
+(puthash "\\itSigma" "𝛴" julia-latexsubs)
+(puthash "\\itTau" "𝛵" julia-latexsubs)
+(puthash "\\itUpsilon" "𝛶" julia-latexsubs)
+(puthash "\\itPhi" "𝛷" julia-latexsubs)
+(puthash "\\itChi" "𝛸" julia-latexsubs)
+(puthash "\\itPsi" "𝛹" julia-latexsubs)
+(puthash "\\itOmega" "𝛺" julia-latexsubs)
+(puthash "\\itnabla" "𝛻" julia-latexsubs)
+(puthash "\\italpha" "𝛼" julia-latexsubs)
+(puthash "\\itbeta" "𝛽" julia-latexsubs)
+(puthash "\\itgamma" "𝛾" julia-latexsubs)
+(puthash "\\itdelta" "𝛿" julia-latexsubs)
+(puthash "\\itepsilon" "𝜀" julia-latexsubs)
+(puthash "\\itzeta" "𝜁" julia-latexsubs)
+(puthash "\\iteta" "𝜂" julia-latexsubs)
+(puthash "\\ittheta" "𝜃" julia-latexsubs)
+(puthash "\\itiota" "𝜄" julia-latexsubs)
+(puthash "\\itkappa" "𝜅" julia-latexsubs)
+(puthash "\\itlambda" "𝜆" julia-latexsubs)
+(puthash "\\itmu" "𝜇" julia-latexsubs)
+(puthash "\\itnu" "𝜈" julia-latexsubs)
+(puthash "\\itxi" "𝜉" julia-latexsubs)
+(puthash "\\itomicron" "𝜊" julia-latexsubs)
+(puthash "\\itpi" "𝜋" julia-latexsubs)
+(puthash "\\itrho" "𝜌" julia-latexsubs)
+(puthash "\\itvarsigma" "𝜍" julia-latexsubs)
+(puthash "\\itsigma" "𝜎" julia-latexsubs)
+(puthash "\\ittau" "𝜏" julia-latexsubs)
+(puthash "\\itupsilon" "𝜐" julia-latexsubs)
+(puthash "\\itphi" "𝜑" julia-latexsubs)
+(puthash "\\itchi" "𝜒" julia-latexsubs)
+(puthash "\\itpsi" "𝜓" julia-latexsubs)
+(puthash "\\itomega" "𝜔" julia-latexsubs)
+(puthash "\\itpartial" "𝜕" julia-latexsubs)
+(puthash "\\itvarepsilon" "𝜖" julia-latexsubs)
+(puthash "\\itvartheta" "𝜗" julia-latexsubs)
+(puthash "\\itvarkappa" "𝜘" julia-latexsubs)
+(puthash "\\itvarphi" "𝜙" julia-latexsubs)
+(puthash "\\itvarrho" "𝜚" julia-latexsubs)
+(puthash "\\itvarpi" "𝜛" julia-latexsubs)
+(puthash "\\biAlpha" "𝜜" julia-latexsubs)
+(puthash "\\biBeta" "𝜝" julia-latexsubs)
+(puthash "\\biGamma" "𝜞" julia-latexsubs)
+(puthash "\\biDelta" "𝜟" julia-latexsubs)
+(puthash "\\biEpsilon" "𝜠" julia-latexsubs)
+(puthash "\\biZeta" "𝜡" julia-latexsubs)
+(puthash "\\biEta" "𝜢" julia-latexsubs)
+(puthash "\\biTheta" "𝜣" julia-latexsubs)
+(puthash "\\biIota" "𝜤" julia-latexsubs)
+(puthash "\\biKappa" "𝜥" julia-latexsubs)
+(puthash "\\biLambda" "𝜦" julia-latexsubs)
+(puthash "\\biMu" "𝜧" julia-latexsubs)
+(puthash "\\biNu" "𝜨" julia-latexsubs)
+(puthash "\\biXi" "𝜩" julia-latexsubs)
+(puthash "\\biOmicron" "𝜪" julia-latexsubs)
+(puthash "\\biPi" "𝜫" julia-latexsubs)
+(puthash "\\biRho" "𝜬" julia-latexsubs)
+(puthash "\\bivarTheta" "𝜭" julia-latexsubs)
+(puthash "\\biSigma" "𝜮" julia-latexsubs)
+(puthash "\\biTau" "𝜯" julia-latexsubs)
+(puthash "\\biUpsilon" "𝜰" julia-latexsubs)
+(puthash "\\biPhi" "𝜱" julia-latexsubs)
+(puthash "\\biChi" "𝜲" julia-latexsubs)
+(puthash "\\biPsi" "𝜳" julia-latexsubs)
+(puthash "\\biOmega" "𝜴" julia-latexsubs)
+(puthash "\\binabla" "𝜵" julia-latexsubs)
+(puthash "\\bialpha" "𝜶" julia-latexsubs)
+(puthash "\\bibeta" "𝜷" julia-latexsubs)
+(puthash "\\bigamma" "𝜸" julia-latexsubs)
+(puthash "\\bidelta" "𝜹" julia-latexsubs)
+(puthash "\\biepsilon" "𝜺" julia-latexsubs)
+(puthash "\\bizeta" "𝜻" julia-latexsubs)
+(puthash "\\bieta" "𝜼" julia-latexsubs)
+(puthash "\\bitheta" "𝜽" julia-latexsubs)
+(puthash "\\biiota" "𝜾" julia-latexsubs)
+(puthash "\\bikappa" "𝜿" julia-latexsubs)
+(puthash "\\bilambda" "𝝀" julia-latexsubs)
+(puthash "\\bimu" "𝝁" julia-latexsubs)
+(puthash "\\binu" "𝝂" julia-latexsubs)
+(puthash "\\bixi" "𝝃" julia-latexsubs)
+(puthash "\\biomicron" "𝝄" julia-latexsubs)
+(puthash "\\bipi" "𝝅" julia-latexsubs)
+(puthash "\\birho" "𝝆" julia-latexsubs)
+(puthash "\\bivarsigma" "𝝇" julia-latexsubs)
+(puthash "\\bisigma" "𝝈" julia-latexsubs)
+(puthash "\\bitau" "𝝉" julia-latexsubs)
+(puthash "\\biupsilon" "𝝊" julia-latexsubs)
+(puthash "\\biphi" "𝝋" julia-latexsubs)
+(puthash "\\bichi" "𝝌" julia-latexsubs)
+(puthash "\\bipsi" "𝝍" julia-latexsubs)
+(puthash "\\biomega" "𝝎" julia-latexsubs)
+(puthash "\\bipartial" "𝝏" julia-latexsubs)
+(puthash "\\bivarepsilon" "𝝐" julia-latexsubs)
+(puthash "\\bivartheta" "𝝑" julia-latexsubs)
+(puthash "\\bivarkappa" "𝝒" julia-latexsubs)
+(puthash "\\bivarphi" "𝝓" julia-latexsubs)
+(puthash "\\bivarrho" "𝝔" julia-latexsubs)
+(puthash "\\bivarpi" "𝝕" julia-latexsubs)
+(puthash "\\bsansAlpha" "𝝖" julia-latexsubs)
+(puthash "\\bsansBeta" "𝝗" julia-latexsubs)
+(puthash "\\bsansGamma" "𝝘" julia-latexsubs)
+(puthash "\\bsansDelta" "𝝙" julia-latexsubs)
+(puthash "\\bsansEpsilon" "𝝚" julia-latexsubs)
+(puthash "\\bsansZeta" "𝝛" julia-latexsubs)
+(puthash "\\bsansEta" "𝝜" julia-latexsubs)
+(puthash "\\bsansTheta" "𝝝" julia-latexsubs)
+(puthash "\\bsansIota" "𝝞" julia-latexsubs)
+(puthash "\\bsansKappa" "𝝟" julia-latexsubs)
+(puthash "\\bsansLambda" "𝝠" julia-latexsubs)
+(puthash "\\bsansMu" "𝝡" julia-latexsubs)
+(puthash "\\bsansNu" "𝝢" julia-latexsubs)
+(puthash "\\bsansXi" "𝝣" julia-latexsubs)
+(puthash "\\bsansOmicron" "𝝤" julia-latexsubs)
+(puthash "\\bsansPi" "𝝥" julia-latexsubs)
+(puthash "\\bsansRho" "𝝦" julia-latexsubs)
+(puthash "\\bsansvarTheta" "𝝧" julia-latexsubs)
+(puthash "\\bsansSigma" "𝝨" julia-latexsubs)
+(puthash "\\bsansTau" "𝝩" julia-latexsubs)
+(puthash "\\bsansUpsilon" "𝝪" julia-latexsubs)
+(puthash "\\bsansPhi" "𝝫" julia-latexsubs)
+(puthash "\\bsansChi" "𝝬" julia-latexsubs)
+(puthash "\\bsansPsi" "𝝭" julia-latexsubs)
+(puthash "\\bsansOmega" "𝝮" julia-latexsubs)
+(puthash "\\bsansnabla" "𝝯" julia-latexsubs)
+(puthash "\\bsansalpha" "𝝰" julia-latexsubs)
+(puthash "\\bsansbeta" "𝝱" julia-latexsubs)
+(puthash "\\bsansgamma" "𝝲" julia-latexsubs)
+(puthash "\\bsansdelta" "𝝳" julia-latexsubs)
+(puthash "\\bsansepsilon" "𝝴" julia-latexsubs)
+(puthash "\\bsanszeta" "𝝵" julia-latexsubs)
+(puthash "\\bsanseta" "𝝶" julia-latexsubs)
+(puthash "\\bsanstheta" "𝝷" julia-latexsubs)
+(puthash "\\bsansiota" "𝝸" julia-latexsubs)
+(puthash "\\bsanskappa" "𝝹" julia-latexsubs)
+(puthash "\\bsanslambda" "𝝺" julia-latexsubs)
+(puthash "\\bsansmu" "𝝻" julia-latexsubs)
+(puthash "\\bsansnu" "𝝼" julia-latexsubs)
+(puthash "\\bsansxi" "𝝽" julia-latexsubs)
+(puthash "\\bsansomicron" "𝝾" julia-latexsubs)
+(puthash "\\bsanspi" "𝝿" julia-latexsubs)
+(puthash "\\bsansrho" "𝞀" julia-latexsubs)
+(puthash "\\bsansvarsigma" "𝞁" julia-latexsubs)
+(puthash "\\bsanssigma" "𝞂" julia-latexsubs)
+(puthash "\\bsanstau" "𝞃" julia-latexsubs)
+(puthash "\\bsansupsilon" "𝞄" julia-latexsubs)
+(puthash "\\bsansphi" "𝞅" julia-latexsubs)
+(puthash "\\bsanschi" "𝞆" julia-latexsubs)
+(puthash "\\bsanspsi" "𝞇" julia-latexsubs)
+(puthash "\\bsansomega" "𝞈" julia-latexsubs)
+(puthash "\\bsanspartial" "𝞉" julia-latexsubs)
+(puthash "\\bsansvarepsilon" "𝞊" julia-latexsubs)
+(puthash "\\bsansvartheta" "𝞋" julia-latexsubs)
+(puthash "\\bsansvarkappa" "𝞌" julia-latexsubs)
+(puthash "\\bsansvarphi" "𝞍" julia-latexsubs)
+(puthash "\\bsansvarrho" "𝞎" julia-latexsubs)
+(puthash "\\bsansvarpi" "𝞏" julia-latexsubs)
+(puthash "\\bisansAlpha" "𝞐" julia-latexsubs)
+(puthash "\\bisansBeta" "𝞑" julia-latexsubs)
+(puthash "\\bisansGamma" "𝞒" julia-latexsubs)
+(puthash "\\bisansDelta" "𝞓" julia-latexsubs)
+(puthash "\\bisansEpsilon" "𝞔" julia-latexsubs)
+(puthash "\\bisansZeta" "𝞕" julia-latexsubs)
+(puthash "\\bisansEta" "𝞖" julia-latexsubs)
+(puthash "\\bisansTheta" "𝞗" julia-latexsubs)
+(puthash "\\bisansIota" "𝞘" julia-latexsubs)
+(puthash "\\bisansKappa" "𝞙" julia-latexsubs)
+(puthash "\\bisansLambda" "𝞚" julia-latexsubs)
+(puthash "\\bisansMu" "𝞛" julia-latexsubs)
+(puthash "\\bisansNu" "𝞜" julia-latexsubs)
+(puthash "\\bisansXi" "𝞝" julia-latexsubs)
+(puthash "\\bisansOmicron" "𝞞" julia-latexsubs)
+(puthash "\\bisansPi" "𝞟" julia-latexsubs)
+(puthash "\\bisansRho" "𝞠" julia-latexsubs)
+(puthash "\\bisansvarTheta" "𝞡" julia-latexsubs)
+(puthash "\\bisansSigma" "𝞢" julia-latexsubs)
+(puthash "\\bisansTau" "𝞣" julia-latexsubs)
+(puthash "\\bisansUpsilon" "𝞤" julia-latexsubs)
+(puthash "\\bisansPhi" "𝞥" julia-latexsubs)
+(puthash "\\bisansChi" "𝞦" julia-latexsubs)
+(puthash "\\bisansPsi" "𝞧" julia-latexsubs)
+(puthash "\\bisansOmega" "𝞨" julia-latexsubs)
+(puthash "\\bisansnabla" "𝞩" julia-latexsubs)
+(puthash "\\bisansalpha" "𝞪" julia-latexsubs)
+(puthash "\\bisansbeta" "𝞫" julia-latexsubs)
+(puthash "\\bisansgamma" "𝞬" julia-latexsubs)
+(puthash "\\bisansdelta" "𝞭" julia-latexsubs)
+(puthash "\\bisansepsilon" "𝞮" julia-latexsubs)
+(puthash "\\bisanszeta" "𝞯" julia-latexsubs)
+(puthash "\\bisanseta" "𝞰" julia-latexsubs)
+(puthash "\\bisanstheta" "𝞱" julia-latexsubs)
+(puthash "\\bisansiota" "𝞲" julia-latexsubs)
+(puthash "\\bisanskappa" "𝞳" julia-latexsubs)
+(puthash "\\bisanslambda" "𝞴" julia-latexsubs)
+(puthash "\\bisansmu" "𝞵" julia-latexsubs)
+(puthash "\\bisansnu" "𝞶" julia-latexsubs)
+(puthash "\\bisansxi" "𝞷" julia-latexsubs)
+(puthash "\\bisansomicron" "𝞸" julia-latexsubs)
+(puthash "\\bisanspi" "𝞹" julia-latexsubs)
+(puthash "\\bisansrho" "𝞺" julia-latexsubs)
+(puthash "\\bisansvarsigma" "𝞻" julia-latexsubs)
+(puthash "\\bisanssigma" "𝞼" julia-latexsubs)
+(puthash "\\bisanstau" "𝞽" julia-latexsubs)
+(puthash "\\bisansupsilon" "𝞾" julia-latexsubs)
+(puthash "\\bisansphi" "𝞿" julia-latexsubs)
+(puthash "\\bisanschi" "𝟀" julia-latexsubs)
+(puthash "\\bisanspsi" "𝟁" julia-latexsubs)
+(puthash "\\bisansomega" "𝟂" julia-latexsubs)
+(puthash "\\bisanspartial" "𝟃" julia-latexsubs)
+(puthash "\\bisansvarepsilon" "𝟄" julia-latexsubs)
+(puthash "\\bisansvartheta" "𝟅" julia-latexsubs)
+(puthash "\\bisansvarkappa" "𝟆" julia-latexsubs)
+(puthash "\\bisansvarphi" "𝟇" julia-latexsubs)
+(puthash "\\bisansvarrho" "𝟈" julia-latexsubs)
+(puthash "\\bisansvarpi" "𝟉" julia-latexsubs)
+(puthash "\\bfDigamma" "𝟊" julia-latexsubs)
+(puthash "\\bfdigamma" "𝟋" julia-latexsubs)
+(puthash "\\bfzero" "𝟎" julia-latexsubs)
+(puthash "\\bfone" "𝟏" julia-latexsubs)
+(puthash "\\bftwo" "𝟐" julia-latexsubs)
+(puthash "\\bfthree" "𝟑" julia-latexsubs)
+(puthash "\\bffour" "𝟒" julia-latexsubs)
+(puthash "\\bffive" "𝟓" julia-latexsubs)
+(puthash "\\bfsix" "𝟔" julia-latexsubs)
+(puthash "\\bfseven" "𝟕" julia-latexsubs)
+(puthash "\\bfeight" "𝟖" julia-latexsubs)
+(puthash "\\bfnine" "𝟗" julia-latexsubs)
+(puthash "\\bbzero" "𝟘" julia-latexsubs)
+(puthash "\\bbone" "𝟙" julia-latexsubs)
+(puthash "\\bbtwo" "𝟚" julia-latexsubs)
+(puthash "\\bbthree" "𝟛" julia-latexsubs)
+(puthash "\\bbfour" "𝟜" julia-latexsubs)
+(puthash "\\bbfive" "𝟝" julia-latexsubs)
+(puthash "\\bbsix" "𝟞" julia-latexsubs)
+(puthash "\\bbseven" "𝟟" julia-latexsubs)
+(puthash "\\bbeight" "𝟠" julia-latexsubs)
+(puthash "\\bbnine" "𝟡" julia-latexsubs)
+(puthash "\\sanszero" "𝟢" julia-latexsubs)
+(puthash "\\sansone" "𝟣" julia-latexsubs)
+(puthash "\\sanstwo" "𝟤" julia-latexsubs)
+(puthash "\\sansthree" "𝟥" julia-latexsubs)
+(puthash "\\sansfour" "𝟦" julia-latexsubs)
+(puthash "\\sansfive" "𝟧" julia-latexsubs)
+(puthash "\\sanssix" "𝟨" julia-latexsubs)
+(puthash "\\sansseven" "𝟩" julia-latexsubs)
+(puthash "\\sanseight" "𝟪" julia-latexsubs)
+(puthash "\\sansnine" "𝟫" julia-latexsubs)
+(puthash "\\bsanszero" "𝟬" julia-latexsubs)
+(puthash "\\bsansone" "𝟭" julia-latexsubs)
+(puthash "\\bsanstwo" "𝟮" julia-latexsubs)
+(puthash "\\bsansthree" "𝟯" julia-latexsubs)
+(puthash "\\bsansfour" "𝟰" julia-latexsubs)
+(puthash "\\bsansfive" "𝟱" julia-latexsubs)
+(puthash "\\bsanssix" "𝟲" julia-latexsubs)
+(puthash "\\bsansseven" "𝟳" julia-latexsubs)
+(puthash "\\bsanseight" "𝟴" julia-latexsubs)
+(puthash "\\bsansnine" "𝟵" julia-latexsubs)
+(puthash "\\ttzero" "𝟶" julia-latexsubs)
+(puthash "\\ttone" "𝟷" julia-latexsubs)
+(puthash "\\tttwo" "𝟸" julia-latexsubs)
+(puthash "\\ttthree" "𝟹" julia-latexsubs)
+(puthash "\\ttfour" "𝟺" julia-latexsubs)
+(puthash "\\ttfive" "𝟻" julia-latexsubs)
+(puthash "\\ttsix" "𝟼" julia-latexsubs)
+(puthash "\\ttseven" "𝟽" julia-latexsubs)
+(puthash "\\tteight" "𝟾" julia-latexsubs)
+(puthash "\\ttnine" "𝟿" julia-latexsubs)
+(puthash "\\:mahjong:" "🀄" julia-latexsubs)
+(puthash "\\:black_joker:" "🃏" julia-latexsubs)
+(puthash "\\:a:" "🅰" julia-latexsubs)
+(puthash "\\:b:" "🅱" julia-latexsubs)
+(puthash "\\:o2:" "🅾" julia-latexsubs)
+(puthash "\\:parking:" "🅿" julia-latexsubs)
+(puthash "\\:ab:" "🆎" julia-latexsubs)
+(puthash "\\:cl:" "🆑" julia-latexsubs)
+(puthash "\\:cool:" "🆒" julia-latexsubs)
+(puthash "\\:free:" "🆓" julia-latexsubs)
+(puthash "\\:id:" "🆔" julia-latexsubs)
+(puthash "\\:new:" "🆕" julia-latexsubs)
+(puthash "\\:ng:" "🆖" julia-latexsubs)
+(puthash "\\:ok:" "🆗" julia-latexsubs)
+(puthash "\\:sos:" "🆘" julia-latexsubs)
+(puthash "\\:up:" "🆙" julia-latexsubs)
+(puthash "\\:vs:" "🆚" julia-latexsubs)
+(puthash "\\:koko:" "🈁" julia-latexsubs)
+(puthash "\\:sa:" "🈂" julia-latexsubs)
+(puthash "\\:u7121:" "🈚" julia-latexsubs)
+(puthash "\\:u6307:" "🈯" julia-latexsubs)
+(puthash "\\:u7981:" "🈲" julia-latexsubs)
+(puthash "\\:u7a7a:" "🈳" julia-latexsubs)
+(puthash "\\:u5408:" "🈴" julia-latexsubs)
+(puthash "\\:u6e80:" "🈵" julia-latexsubs)
+(puthash "\\:u6709:" "🈶" julia-latexsubs)
+(puthash "\\:u6708:" "🈷" julia-latexsubs)
+(puthash "\\:u7533:" "🈸" julia-latexsubs)
+(puthash "\\:u5272:" "🈹" julia-latexsubs)
+(puthash "\\:u55b6:" "🈺" julia-latexsubs)
+(puthash "\\:ideograph_advantage:" "🉐" julia-latexsubs)
+(puthash "\\:accept:" "🉑" julia-latexsubs)
+(puthash "\\:cyclone:" "🌀" julia-latexsubs)
+(puthash "\\:foggy:" "🌁" julia-latexsubs)
+(puthash "\\:closed_umbrella:" "🌂" julia-latexsubs)
+(puthash "\\:night_with_stars:" "🌃" julia-latexsubs)
+(puthash "\\:sunrise_over_mountains:" "🌄" julia-latexsubs)
+(puthash "\\:sunrise:" "🌅" julia-latexsubs)
+(puthash "\\:city_sunset:" "🌆" julia-latexsubs)
+(puthash "\\:city_sunrise:" "🌇" julia-latexsubs)
+(puthash "\\:rainbow:" "🌈" julia-latexsubs)
+(puthash "\\:bridge_at_night:" "🌉" julia-latexsubs)
+(puthash "\\:ocean:" "🌊" julia-latexsubs)
+(puthash "\\:volcano:" "🌋" julia-latexsubs)
+(puthash "\\:milky_way:" "🌌" julia-latexsubs)
+(puthash "\\:earth_africa:" "🌍" julia-latexsubs)
+(puthash "\\:earth_americas:" "🌎" julia-latexsubs)
+(puthash "\\:earth_asia:" "🌏" julia-latexsubs)
+(puthash "\\:globe_with_meridians:" "🌐" julia-latexsubs)
+(puthash "\\:new_moon:" "🌑" julia-latexsubs)
+(puthash "\\:waxing_crescent_moon:" "🌒" julia-latexsubs)
+(puthash "\\:first_quarter_moon:" "🌓" julia-latexsubs)
+(puthash "\\:moon:" "🌔" julia-latexsubs)
+(puthash "\\:full_moon:" "🌕" julia-latexsubs)
+(puthash "\\:waning_gibbous_moon:" "🌖" julia-latexsubs)
+(puthash "\\:last_quarter_moon:" "🌗" julia-latexsubs)
+(puthash "\\:waning_crescent_moon:" "🌘" julia-latexsubs)
+(puthash "\\:crescent_moon:" "🌙" julia-latexsubs)
+(puthash "\\:new_moon_with_face:" "🌚" julia-latexsubs)
+(puthash "\\:first_quarter_moon_with_face:" "🌛" julia-latexsubs)
+(puthash "\\:last_quarter_moon_with_face:" "🌜" julia-latexsubs)
+(puthash "\\:full_moon_with_face:" "🌝" julia-latexsubs)
+(puthash "\\:sun_with_face:" "🌞" julia-latexsubs)
+(puthash "\\:star2:" "🌟" julia-latexsubs)
+(puthash "\\:stars:" "🌠" julia-latexsubs)
+(puthash "\\:chestnut:" "🌰" julia-latexsubs)
+(puthash "\\:seedling:" "🌱" julia-latexsubs)
+(puthash "\\:evergreen_tree:" "🌲" julia-latexsubs)
+(puthash "\\:deciduous_tree:" "🌳" julia-latexsubs)
+(puthash "\\:palm_tree:" "🌴" julia-latexsubs)
+(puthash "\\:cactus:" "🌵" julia-latexsubs)
+(puthash "\\:tulip:" "🌷" julia-latexsubs)
+(puthash "\\:cherry_blossom:" "🌸" julia-latexsubs)
+(puthash "\\:rose:" "🌹" julia-latexsubs)
+(puthash "\\:hibiscus:" "🌺" julia-latexsubs)
+(puthash "\\:sunflower:" "🌻" julia-latexsubs)
+(puthash "\\:blossom:" "🌼" julia-latexsubs)
+(puthash "\\:corn:" "🌽" julia-latexsubs)
+(puthash "\\:ear_of_rice:" "🌾" julia-latexsubs)
+(puthash "\\:herb:" "🌿" julia-latexsubs)
+(puthash "\\:four_leaf_clover:" "🍀" julia-latexsubs)
+(puthash "\\:maple_leaf:" "🍁" julia-latexsubs)
+(puthash "\\:fallen_leaf:" "🍂" julia-latexsubs)
+(puthash "\\:leaves:" "🍃" julia-latexsubs)
+(puthash "\\:mushroom:" "🍄" julia-latexsubs)
+(puthash "\\:tomato:" "🍅" julia-latexsubs)
+(puthash "\\:eggplant:" "🍆" julia-latexsubs)
+(puthash "\\:grapes:" "🍇" julia-latexsubs)
+(puthash "\\:melon:" "🍈" julia-latexsubs)
+(puthash "\\:watermelon:" "🍉" julia-latexsubs)
+(puthash "\\:tangerine:" "🍊" julia-latexsubs)
+(puthash "\\:lemon:" "🍋" julia-latexsubs)
+(puthash "\\:banana:" "🍌" julia-latexsubs)
+(puthash "\\:pineapple:" "🍍" julia-latexsubs)
+(puthash "\\:apple:" "🍎" julia-latexsubs)
+(puthash "\\:green_apple:" "🍏" julia-latexsubs)
+(puthash "\\:pear:" "🍐" julia-latexsubs)
+(puthash "\\:peach:" "🍑" julia-latexsubs)
+(puthash "\\:cherries:" "🍒" julia-latexsubs)
+(puthash "\\:strawberry:" "🍓" julia-latexsubs)
+(puthash "\\:hamburger:" "🍔" julia-latexsubs)
+(puthash "\\:pizza:" "🍕" julia-latexsubs)
+(puthash "\\:meat_on_bone:" "🍖" julia-latexsubs)
+(puthash "\\:poultry_leg:" "🍗" julia-latexsubs)
+(puthash "\\:rice_cracker:" "🍘" julia-latexsubs)
+(puthash "\\:rice_ball:" "🍙" julia-latexsubs)
+(puthash "\\:rice:" "🍚" julia-latexsubs)
+(puthash "\\:curry:" "🍛" julia-latexsubs)
+(puthash "\\:ramen:" "🍜" julia-latexsubs)
+(puthash "\\:spaghetti:" "🍝" julia-latexsubs)
+(puthash "\\:bread:" "🍞" julia-latexsubs)
+(puthash "\\:fries:" "🍟" julia-latexsubs)
+(puthash "\\:sweet_potato:" "🍠" julia-latexsubs)
+(puthash "\\:dango:" "🍡" julia-latexsubs)
+(puthash "\\:oden:" "🍢" julia-latexsubs)
+(puthash "\\:sushi:" "🍣" julia-latexsubs)
+(puthash "\\:fried_shrimp:" "🍤" julia-latexsubs)
+(puthash "\\:fish_cake:" "🍥" julia-latexsubs)
+(puthash "\\:icecream:" "🍦" julia-latexsubs)
+(puthash "\\:shaved_ice:" "🍧" julia-latexsubs)
+(puthash "\\:ice_cream:" "🍨" julia-latexsubs)
+(puthash "\\:doughnut:" "🍩" julia-latexsubs)
+(puthash "\\:cookie:" "🍪" julia-latexsubs)
+(puthash "\\:chocolate_bar:" "🍫" julia-latexsubs)
+(puthash "\\:candy:" "🍬" julia-latexsubs)
+(puthash "\\:lollipop:" "🍭" julia-latexsubs)
+(puthash "\\:custard:" "🍮" julia-latexsubs)
+(puthash "\\:honey_pot:" "🍯" julia-latexsubs)
+(puthash "\\:cake:" "🍰" julia-latexsubs)
+(puthash "\\:bento:" "🍱" julia-latexsubs)
+(puthash "\\:stew:" "🍲" julia-latexsubs)
+(puthash "\\:egg:" "🍳" julia-latexsubs)
+(puthash "\\:fork_and_knife:" "🍴" julia-latexsubs)
+(puthash "\\:tea:" "🍵" julia-latexsubs)
+(puthash "\\:sake:" "🍶" julia-latexsubs)
+(puthash "\\:wine_glass:" "🍷" julia-latexsubs)
+(puthash "\\:cocktail:" "🍸" julia-latexsubs)
+(puthash "\\:tropical_drink:" "🍹" julia-latexsubs)
+(puthash "\\:beer:" "🍺" julia-latexsubs)
+(puthash "\\:beers:" "🍻" julia-latexsubs)
+(puthash "\\:baby_bottle:" "🍼" julia-latexsubs)
+(puthash "\\:ribbon:" "🎀" julia-latexsubs)
+(puthash "\\:gift:" "🎁" julia-latexsubs)
+(puthash "\\:birthday:" "🎂" julia-latexsubs)
+(puthash "\\:jack_o_lantern:" "🎃" julia-latexsubs)
+(puthash "\\:christmas_tree:" "🎄" julia-latexsubs)
+(puthash "\\:santa:" "🎅" julia-latexsubs)
+(puthash "\\:fireworks:" "🎆" julia-latexsubs)
+(puthash "\\:sparkler:" "🎇" julia-latexsubs)
+(puthash "\\:balloon:" "🎈" julia-latexsubs)
+(puthash "\\:tada:" "🎉" julia-latexsubs)
+(puthash "\\:confetti_ball:" "🎊" julia-latexsubs)
+(puthash "\\:tanabata_tree:" "🎋" julia-latexsubs)
+(puthash "\\:crossed_flags:" "🎌" julia-latexsubs)
+(puthash "\\:bamboo:" "🎍" julia-latexsubs)
+(puthash "\\:dolls:" "🎎" julia-latexsubs)
+(puthash "\\:flags:" "🎏" julia-latexsubs)
+(puthash "\\:wind_chime:" "🎐" julia-latexsubs)
+(puthash "\\:rice_scene:" "🎑" julia-latexsubs)
+(puthash "\\:school_satchel:" "🎒" julia-latexsubs)
+(puthash "\\:mortar_board:" "🎓" julia-latexsubs)
+(puthash "\\:carousel_horse:" "🎠" julia-latexsubs)
+(puthash "\\:ferris_wheel:" "🎡" julia-latexsubs)
+(puthash "\\:roller_coaster:" "🎢" julia-latexsubs)
+(puthash "\\:fishing_pole_and_fish:" "🎣" julia-latexsubs)
+(puthash "\\:microphone:" "🎤" julia-latexsubs)
+(puthash "\\:movie_camera:" "🎥" julia-latexsubs)
+(puthash "\\:cinema:" "🎦" julia-latexsubs)
+(puthash "\\:headphones:" "🎧" julia-latexsubs)
+(puthash "\\:art:" "🎨" julia-latexsubs)
+(puthash "\\:tophat:" "🎩" julia-latexsubs)
+(puthash "\\:circus_tent:" "🎪" julia-latexsubs)
+(puthash "\\:ticket:" "🎫" julia-latexsubs)
+(puthash "\\:clapper:" "🎬" julia-latexsubs)
+(puthash "\\:performing_arts:" "🎭" julia-latexsubs)
+(puthash "\\:video_game:" "🎮" julia-latexsubs)
+(puthash "\\:dart:" "🎯" julia-latexsubs)
+(puthash "\\:slot_machine:" "🎰" julia-latexsubs)
+(puthash "\\:8ball:" "🎱" julia-latexsubs)
+(puthash "\\:game_die:" "🎲" julia-latexsubs)
+(puthash "\\:bowling:" "🎳" julia-latexsubs)
+(puthash "\\:flower_playing_cards:" "🎴" julia-latexsubs)
+(puthash "\\:musical_note:" "🎵" julia-latexsubs)
+(puthash "\\:notes:" "🎶" julia-latexsubs)
+(puthash "\\:saxophone:" "🎷" julia-latexsubs)
+(puthash "\\:guitar:" "🎸" julia-latexsubs)
+(puthash "\\:musical_keyboard:" "🎹" julia-latexsubs)
+(puthash "\\:trumpet:" "🎺" julia-latexsubs)
+(puthash "\\:violin:" "🎻" julia-latexsubs)
+(puthash "\\:musical_score:" "🎼" julia-latexsubs)
+(puthash "\\:running_shirt_with_sash:" "🎽" julia-latexsubs)
+(puthash "\\:tennis:" "🎾" julia-latexsubs)
+(puthash "\\:ski:" "🎿" julia-latexsubs)
+(puthash "\\:basketball:" "🏀" julia-latexsubs)
+(puthash "\\:checkered_flag:" "🏁" julia-latexsubs)
+(puthash "\\:snowboarder:" "🏂" julia-latexsubs)
+(puthash "\\:runner:" "🏃" julia-latexsubs)
+(puthash "\\:surfer:" "🏄" julia-latexsubs)
+(puthash "\\:trophy:" "🏆" julia-latexsubs)
+(puthash "\\:horse_racing:" "🏇" julia-latexsubs)
+(puthash "\\:football:" "🏈" julia-latexsubs)
+(puthash "\\:rugby_football:" "🏉" julia-latexsubs)
+(puthash "\\:swimmer:" "🏊" julia-latexsubs)
+(puthash "\\:house:" "🏠" julia-latexsubs)
+(puthash "\\:house_with_garden:" "🏡" julia-latexsubs)
+(puthash "\\:office:" "🏢" julia-latexsubs)
+(puthash "\\:post_office:" "🏣" julia-latexsubs)
+(puthash "\\:european_post_office:" "🏤" julia-latexsubs)
+(puthash "\\:hospital:" "🏥" julia-latexsubs)
+(puthash "\\:bank:" "🏦" julia-latexsubs)
+(puthash "\\:atm:" "🏧" julia-latexsubs)
+(puthash "\\:hotel:" "🏨" julia-latexsubs)
+(puthash "\\:love_hotel:" "🏩" julia-latexsubs)
+(puthash "\\:convenience_store:" "🏪" julia-latexsubs)
+(puthash "\\:school:" "🏫" julia-latexsubs)
+(puthash "\\:department_store:" "🏬" julia-latexsubs)
+(puthash "\\:factory:" "🏭" julia-latexsubs)
+(puthash "\\:izakaya_lantern:" "🏮" julia-latexsubs)
+(puthash "\\:japanese_castle:" "🏯" julia-latexsubs)
+(puthash "\\:european_castle:" "🏰" julia-latexsubs)
+(puthash "\\:skin-tone-2:" "🏻" julia-latexsubs)
+(puthash "\\:skin-tone-3:" "🏼" julia-latexsubs)
+(puthash "\\:skin-tone-4:" "🏽" julia-latexsubs)
+(puthash "\\:skin-tone-5:" "🏾" julia-latexsubs)
+(puthash "\\:skin-tone-6:" "🏿" julia-latexsubs)
+(puthash "\\:rat:" "🐀" julia-latexsubs)
+(puthash "\\:mouse2:" "🐁" julia-latexsubs)
+(puthash "\\:ox:" "🐂" julia-latexsubs)
+(puthash "\\:water_buffalo:" "🐃" julia-latexsubs)
+(puthash "\\:cow2:" "🐄" julia-latexsubs)
+(puthash "\\:tiger2:" "🐅" julia-latexsubs)
+(puthash "\\:leopard:" "🐆" julia-latexsubs)
+(puthash "\\:rabbit2:" "🐇" julia-latexsubs)
+(puthash "\\:cat2:" "🐈" julia-latexsubs)
+(puthash "\\:dragon:" "🐉" julia-latexsubs)
+(puthash "\\:crocodile:" "🐊" julia-latexsubs)
+(puthash "\\:whale2:" "🐋" julia-latexsubs)
+(puthash "\\:snail:" "🐌" julia-latexsubs)
+(puthash "\\:snake:" "🐍" julia-latexsubs)
+(puthash "\\:racehorse:" "🐎" julia-latexsubs)
+(puthash "\\:ram:" "🐏" julia-latexsubs)
+(puthash "\\:goat:" "🐐" julia-latexsubs)
+(puthash "\\:sheep:" "🐑" julia-latexsubs)
+(puthash "\\:monkey:" "🐒" julia-latexsubs)
+(puthash "\\:rooster:" "🐓" julia-latexsubs)
+(puthash "\\:chicken:" "🐔" julia-latexsubs)
+(puthash "\\:dog2:" "🐕" julia-latexsubs)
+(puthash "\\:pig2:" "🐖" julia-latexsubs)
+(puthash "\\:boar:" "🐗" julia-latexsubs)
+(puthash "\\:elephant:" "🐘" julia-latexsubs)
+(puthash "\\:octopus:" "🐙" julia-latexsubs)
+(puthash "\\:shell:" "🐚" julia-latexsubs)
+(puthash "\\:bug:" "🐛" julia-latexsubs)
+(puthash "\\:ant:" "🐜" julia-latexsubs)
+(puthash "\\:bee:" "🐝" julia-latexsubs)
+(puthash "\\:beetle:" "🐞" julia-latexsubs)
+(puthash "\\:fish:" "🐟" julia-latexsubs)
+(puthash "\\:tropical_fish:" "🐠" julia-latexsubs)
+(puthash "\\:blowfish:" "🐡" julia-latexsubs)
+(puthash "\\:turtle:" "🐢" julia-latexsubs)
+(puthash "\\:hatching_chick:" "🐣" julia-latexsubs)
+(puthash "\\:baby_chick:" "🐤" julia-latexsubs)
+(puthash "\\:hatched_chick:" "🐥" julia-latexsubs)
+(puthash "\\:bird:" "🐦" julia-latexsubs)
+(puthash "\\:penguin:" "🐧" julia-latexsubs)
+(puthash "\\:koala:" "🐨" julia-latexsubs)
+(puthash "\\:poodle:" "🐩" julia-latexsubs)
+(puthash "\\:dromedary_camel:" "🐪" julia-latexsubs)
+(puthash "\\:camel:" "🐫" julia-latexsubs)
+(puthash "\\:dolphin:" "🐬" julia-latexsubs)
+(puthash "\\:mouse:" "🐭" julia-latexsubs)
+(puthash "\\:cow:" "🐮" julia-latexsubs)
+(puthash "\\:tiger:" "🐯" julia-latexsubs)
+(puthash "\\:rabbit:" "🐰" julia-latexsubs)
+(puthash "\\:cat:" "🐱" julia-latexsubs)
+(puthash "\\:dragon_face:" "🐲" julia-latexsubs)
+(puthash "\\:whale:" "🐳" julia-latexsubs)
+(puthash "\\:horse:" "🐴" julia-latexsubs)
+(puthash "\\:monkey_face:" "🐵" julia-latexsubs)
+(puthash "\\:dog:" "🐶" julia-latexsubs)
+(puthash "\\:pig:" "🐷" julia-latexsubs)
+(puthash "\\:frog:" "🐸" julia-latexsubs)
+(puthash "\\:hamster:" "🐹" julia-latexsubs)
+(puthash "\\:wolf:" "🐺" julia-latexsubs)
+(puthash "\\:bear:" "🐻" julia-latexsubs)
+(puthash "\\:panda_face:" "🐼" julia-latexsubs)
+(puthash "\\:pig_nose:" "🐽" julia-latexsubs)
+(puthash "\\:feet:" "🐾" julia-latexsubs)
+(puthash "\\:eyes:" "👀" julia-latexsubs)
+(puthash "\\:ear:" "👂" julia-latexsubs)
+(puthash "\\:nose:" "👃" julia-latexsubs)
+(puthash "\\:lips:" "👄" julia-latexsubs)
+(puthash "\\:tongue:" "👅" julia-latexsubs)
+(puthash "\\:point_up_2:" "👆" julia-latexsubs)
+(puthash "\\:point_down:" "👇" julia-latexsubs)
+(puthash "\\:point_left:" "👈" julia-latexsubs)
+(puthash "\\:point_right:" "👉" julia-latexsubs)
+(puthash "\\:facepunch:" "👊" julia-latexsubs)
+(puthash "\\:wave:" "👋" julia-latexsubs)
+(puthash "\\:ok_hand:" "👌" julia-latexsubs)
+(puthash "\\:+1:" "👍" julia-latexsubs)
+(puthash "\\:-1:" "👎" julia-latexsubs)
+(puthash "\\:clap:" "👏" julia-latexsubs)
+(puthash "\\:open_hands:" "👐" julia-latexsubs)
+(puthash "\\:crown:" "👑" julia-latexsubs)
+(puthash "\\:womans_hat:" "👒" julia-latexsubs)
+(puthash "\\:eyeglasses:" "👓" julia-latexsubs)
+(puthash "\\:necktie:" "👔" julia-latexsubs)
+(puthash "\\:shirt:" "👕" julia-latexsubs)
+(puthash "\\:jeans:" "👖" julia-latexsubs)
+(puthash "\\:dress:" "👗" julia-latexsubs)
+(puthash "\\:kimono:" "👘" julia-latexsubs)
+(puthash "\\:bikini:" "👙" julia-latexsubs)
+(puthash "\\:womans_clothes:" "👚" julia-latexsubs)
+(puthash "\\:purse:" "👛" julia-latexsubs)
+(puthash "\\:handbag:" "👜" julia-latexsubs)
+(puthash "\\:pouch:" "👝" julia-latexsubs)
+(puthash "\\:mans_shoe:" "👞" julia-latexsubs)
+(puthash "\\:athletic_shoe:" "👟" julia-latexsubs)
+(puthash "\\:high_heel:" "👠" julia-latexsubs)
+(puthash "\\:sandal:" "👡" julia-latexsubs)
+(puthash "\\:boot:" "👢" julia-latexsubs)
+(puthash "\\:footprints:" "👣" julia-latexsubs)
+(puthash "\\:bust_in_silhouette:" "👤" julia-latexsubs)
+(puthash "\\:busts_in_silhouette:" "👥" julia-latexsubs)
+(puthash "\\:boy:" "👦" julia-latexsubs)
+(puthash "\\:girl:" "👧" julia-latexsubs)
+(puthash "\\:man:" "👨" julia-latexsubs)
+(puthash "\\:woman:" "👩" julia-latexsubs)
+(puthash "\\:family:" "👪" julia-latexsubs)
+(puthash "\\:couple:" "👫" julia-latexsubs)
+(puthash "\\:two_men_holding_hands:" "👬" julia-latexsubs)
+(puthash "\\:two_women_holding_hands:" "👭" julia-latexsubs)
+(puthash "\\:cop:" "👮" julia-latexsubs)
+(puthash "\\:dancers:" "👯" julia-latexsubs)
+(puthash "\\:bride_with_veil:" "👰" julia-latexsubs)
+(puthash "\\:person_with_blond_hair:" "👱" julia-latexsubs)
+(puthash "\\:man_with_gua_pi_mao:" "👲" julia-latexsubs)
+(puthash "\\:man_with_turban:" "👳" julia-latexsubs)
+(puthash "\\:older_man:" "👴" julia-latexsubs)
+(puthash "\\:older_woman:" "👵" julia-latexsubs)
+(puthash "\\:baby:" "👶" julia-latexsubs)
+(puthash "\\:construction_worker:" "👷" julia-latexsubs)
+(puthash "\\:princess:" "👸" julia-latexsubs)
+(puthash "\\:japanese_ogre:" "👹" julia-latexsubs)
+(puthash "\\:japanese_goblin:" "👺" julia-latexsubs)
+(puthash "\\:ghost:" "👻" julia-latexsubs)
+(puthash "\\:angel:" "👼" julia-latexsubs)
+(puthash "\\:alien:" "👽" julia-latexsubs)
+(puthash "\\:space_invader:" "👾" julia-latexsubs)
+(puthash "\\:imp:" "👿" julia-latexsubs)
+(puthash "\\:skull:" "💀" julia-latexsubs)
+(puthash "\\:information_desk_person:" "💁" julia-latexsubs)
+(puthash "\\:guardsman:" "💂" julia-latexsubs)
+(puthash "\\:dancer:" "💃" julia-latexsubs)
+(puthash "\\:lipstick:" "💄" julia-latexsubs)
+(puthash "\\:nail_care:" "💅" julia-latexsubs)
+(puthash "\\:massage:" "💆" julia-latexsubs)
+(puthash "\\:haircut:" "💇" julia-latexsubs)
+(puthash "\\:barber:" "💈" julia-latexsubs)
+(puthash "\\:syringe:" "💉" julia-latexsubs)
+(puthash "\\:pill:" "💊" julia-latexsubs)
+(puthash "\\:kiss:" "💋" julia-latexsubs)
+(puthash "\\:love_letter:" "💌" julia-latexsubs)
+(puthash "\\:ring:" "💍" julia-latexsubs)
+(puthash "\\:gem:" "💎" julia-latexsubs)
+(puthash "\\:couplekiss:" "💏" julia-latexsubs)
+(puthash "\\:bouquet:" "💐" julia-latexsubs)
+(puthash "\\:couple_with_heart:" "💑" julia-latexsubs)
+(puthash "\\:wedding:" "💒" julia-latexsubs)
+(puthash "\\:heartbeat:" "💓" julia-latexsubs)
+(puthash "\\:broken_heart:" "💔" julia-latexsubs)
+(puthash "\\:two_hearts:" "💕" julia-latexsubs)
+(puthash "\\:sparkling_heart:" "💖" julia-latexsubs)
+(puthash "\\:heartpulse:" "💗" julia-latexsubs)
+(puthash "\\:cupid:" "💘" julia-latexsubs)
+(puthash "\\:blue_heart:" "💙" julia-latexsubs)
+(puthash "\\:green_heart:" "💚" julia-latexsubs)
+(puthash "\\:yellow_heart:" "💛" julia-latexsubs)
+(puthash "\\:purple_heart:" "💜" julia-latexsubs)
+(puthash "\\:gift_heart:" "💝" julia-latexsubs)
+(puthash "\\:revolving_hearts:" "💞" julia-latexsubs)
+(puthash "\\:heart_decoration:" "💟" julia-latexsubs)
+(puthash "\\:diamond_shape_with_a_dot_inside:" "💠" julia-latexsubs)
+(puthash "\\:bulb:" "💡" julia-latexsubs)
+(puthash "\\:anger:" "💢" julia-latexsubs)
+(puthash "\\:bomb:" "💣" julia-latexsubs)
+(puthash "\\:zzz:" "💤" julia-latexsubs)
+(puthash "\\:boom:" "💥" julia-latexsubs)
+(puthash "\\:sweat_drops:" "💦" julia-latexsubs)
+(puthash "\\:droplet:" "💧" julia-latexsubs)
+(puthash "\\:dash:" "💨" julia-latexsubs)
+(puthash "\\:hankey:" "💩" julia-latexsubs)
+(puthash "\\:muscle:" "💪" julia-latexsubs)
+(puthash "\\:dizzy:" "💫" julia-latexsubs)
+(puthash "\\:speech_balloon:" "💬" julia-latexsubs)
+(puthash "\\:thought_balloon:" "💭" julia-latexsubs)
+(puthash "\\:white_flower:" "💮" julia-latexsubs)
+(puthash "\\:100:" "💯" julia-latexsubs)
+(puthash "\\:moneybag:" "💰" julia-latexsubs)
+(puthash "\\:currency_exchange:" "💱" julia-latexsubs)
+(puthash "\\:heavy_dollar_sign:" "💲" julia-latexsubs)
+(puthash "\\:credit_card:" "💳" julia-latexsubs)
+(puthash "\\:yen:" "💴" julia-latexsubs)
+(puthash "\\:dollar:" "💵" julia-latexsubs)
+(puthash "\\:euro:" "💶" julia-latexsubs)
+(puthash "\\:pound:" "💷" julia-latexsubs)
+(puthash "\\:money_with_wings:" "💸" julia-latexsubs)
+(puthash "\\:chart:" "💹" julia-latexsubs)
+(puthash "\\:seat:" "💺" julia-latexsubs)
+(puthash "\\:computer:" "💻" julia-latexsubs)
+(puthash "\\:briefcase:" "💼" julia-latexsubs)
+(puthash "\\:minidisc:" "💽" julia-latexsubs)
+(puthash "\\:floppy_disk:" "💾" julia-latexsubs)
+(puthash "\\:cd:" "💿" julia-latexsubs)
+(puthash "\\:dvd:" "📀" julia-latexsubs)
+(puthash "\\:file_folder:" "📁" julia-latexsubs)
+(puthash "\\:open_file_folder:" "📂" julia-latexsubs)
+(puthash "\\:page_with_curl:" "📃" julia-latexsubs)
+(puthash "\\:page_facing_up:" "📄" julia-latexsubs)
+(puthash "\\:date:" "📅" julia-latexsubs)
+(puthash "\\:calendar:" "📆" julia-latexsubs)
+(puthash "\\:card_index:" "📇" julia-latexsubs)
+(puthash "\\:chart_with_upwards_trend:" "📈" julia-latexsubs)
+(puthash "\\:chart_with_downwards_trend:" "📉" julia-latexsubs)
+(puthash "\\:bar_chart:" "📊" julia-latexsubs)
+(puthash "\\:clipboard:" "📋" julia-latexsubs)
+(puthash "\\:pushpin:" "📌" julia-latexsubs)
+(puthash "\\:round_pushpin:" "📍" julia-latexsubs)
+(puthash "\\:paperclip:" "📎" julia-latexsubs)
+(puthash "\\:straight_ruler:" "📏" julia-latexsubs)
+(puthash "\\:triangular_ruler:" "📐" julia-latexsubs)
+(puthash "\\:bookmark_tabs:" "📑" julia-latexsubs)
+(puthash "\\:ledger:" "📒" julia-latexsubs)
+(puthash "\\:notebook:" "📓" julia-latexsubs)
+(puthash "\\:notebook_with_decorative_cover:" "📔" julia-latexsubs)
+(puthash "\\:closed_book:" "📕" julia-latexsubs)
+(puthash "\\:book:" "📖" julia-latexsubs)
+(puthash "\\:green_book:" "📗" julia-latexsubs)
+(puthash "\\:blue_book:" "📘" julia-latexsubs)
+(puthash "\\:orange_book:" "📙" julia-latexsubs)
+(puthash "\\:books:" "📚" julia-latexsubs)
+(puthash "\\:name_badge:" "📛" julia-latexsubs)
+(puthash "\\:scroll:" "📜" julia-latexsubs)
+(puthash "\\:memo:" "📝" julia-latexsubs)
+(puthash "\\:telephone_receiver:" "📞" julia-latexsubs)
+(puthash "\\:pager:" "📟" julia-latexsubs)
+(puthash "\\:fax:" "📠" julia-latexsubs)
+(puthash "\\:satellite:" "📡" julia-latexsubs)
+(puthash "\\:loudspeaker:" "📢" julia-latexsubs)
+(puthash "\\:mega:" "📣" julia-latexsubs)
+(puthash "\\:outbox_tray:" "📤" julia-latexsubs)
+(puthash "\\:inbox_tray:" "📥" julia-latexsubs)
+(puthash "\\:package:" "📦" julia-latexsubs)
+(puthash "\\:e-mail:" "📧" julia-latexsubs)
+(puthash "\\:incoming_envelope:" "📨" julia-latexsubs)
+(puthash "\\:envelope_with_arrow:" "📩" julia-latexsubs)
+(puthash "\\:mailbox_closed:" "📪" julia-latexsubs)
+(puthash "\\:mailbox:" "📫" julia-latexsubs)
+(puthash "\\:mailbox_with_mail:" "📬" julia-latexsubs)
+(puthash "\\:mailbox_with_no_mail:" "📭" julia-latexsubs)
+(puthash "\\:postbox:" "📮" julia-latexsubs)
+(puthash "\\:postal_horn:" "📯" julia-latexsubs)
+(puthash "\\:newspaper:" "📰" julia-latexsubs)
+(puthash "\\:iphone:" "📱" julia-latexsubs)
+(puthash "\\:calling:" "📲" julia-latexsubs)
+(puthash "\\:vibration_mode:" "📳" julia-latexsubs)
+(puthash "\\:mobile_phone_off:" "📴" julia-latexsubs)
+(puthash "\\:no_mobile_phones:" "📵" julia-latexsubs)
+(puthash "\\:signal_strength:" "📶" julia-latexsubs)
+(puthash "\\:camera:" "📷" julia-latexsubs)
+(puthash "\\:video_camera:" "📹" julia-latexsubs)
+(puthash "\\:tv:" "📺" julia-latexsubs)
+(puthash "\\:radio:" "📻" julia-latexsubs)
+(puthash "\\:vhs:" "📼" julia-latexsubs)
+(puthash "\\:twisted_rightwards_arrows:" "🔀" julia-latexsubs)
+(puthash "\\:repeat:" "🔁" julia-latexsubs)
+(puthash "\\:repeat_one:" "🔂" julia-latexsubs)
+(puthash "\\:arrows_clockwise:" "🔃" julia-latexsubs)
+(puthash "\\:arrows_counterclockwise:" "🔄" julia-latexsubs)
+(puthash "\\:low_brightness:" "🔅" julia-latexsubs)
+(puthash "\\:high_brightness:" "🔆" julia-latexsubs)
+(puthash "\\:mute:" "🔇" julia-latexsubs)
+(puthash "\\:speaker:" "🔈" julia-latexsubs)
+(puthash "\\:sound:" "🔉" julia-latexsubs)
+(puthash "\\:loud_sound:" "🔊" julia-latexsubs)
+(puthash "\\:battery:" "🔋" julia-latexsubs)
+(puthash "\\:electric_plug:" "🔌" julia-latexsubs)
+(puthash "\\:mag:" "🔍" julia-latexsubs)
+(puthash "\\:mag_right:" "🔎" julia-latexsubs)
+(puthash "\\:lock_with_ink_pen:" "🔏" julia-latexsubs)
+(puthash "\\:closed_lock_with_key:" "🔐" julia-latexsubs)
+(puthash "\\:key:" "🔑" julia-latexsubs)
+(puthash "\\:lock:" "🔒" julia-latexsubs)
+(puthash "\\:unlock:" "🔓" julia-latexsubs)
+(puthash "\\:bell:" "🔔" julia-latexsubs)
+(puthash "\\:no_bell:" "🔕" julia-latexsubs)
+(puthash "\\:bookmark:" "🔖" julia-latexsubs)
+(puthash "\\:link:" "🔗" julia-latexsubs)
+(puthash "\\:radio_button:" "🔘" julia-latexsubs)
+(puthash "\\:back:" "🔙" julia-latexsubs)
+(puthash "\\:end:" "🔚" julia-latexsubs)
+(puthash "\\:on:" "🔛" julia-latexsubs)
+(puthash "\\:soon:" "🔜" julia-latexsubs)
+(puthash "\\:top:" "🔝" julia-latexsubs)
+(puthash "\\:underage:" "🔞" julia-latexsubs)
+(puthash "\\:keycap_ten:" "🔟" julia-latexsubs)
+(puthash "\\:capital_abcd:" "🔠" julia-latexsubs)
+(puthash "\\:abcd:" "🔡" julia-latexsubs)
+(puthash "\\:1234:" "🔢" julia-latexsubs)
+(puthash "\\:symbols:" "🔣" julia-latexsubs)
+(puthash "\\:abc:" "🔤" julia-latexsubs)
+(puthash "\\:fire:" "🔥" julia-latexsubs)
+(puthash "\\:flashlight:" "🔦" julia-latexsubs)
+(puthash "\\:wrench:" "🔧" julia-latexsubs)
+(puthash "\\:hammer:" "🔨" julia-latexsubs)
+(puthash "\\:nut_and_bolt:" "🔩" julia-latexsubs)
+(puthash "\\:hocho:" "🔪" julia-latexsubs)
+(puthash "\\:gun:" "🔫" julia-latexsubs)
+(puthash "\\:microscope:" "🔬" julia-latexsubs)
+(puthash "\\:telescope:" "🔭" julia-latexsubs)
+(puthash "\\:crystal_ball:" "🔮" julia-latexsubs)
+(puthash "\\:six_pointed_star:" "🔯" julia-latexsubs)
+(puthash "\\:beginner:" "🔰" julia-latexsubs)
+(puthash "\\:trident:" "🔱" julia-latexsubs)
+(puthash "\\:black_square_button:" "🔲" julia-latexsubs)
+(puthash "\\:white_square_button:" "🔳" julia-latexsubs)
+(puthash "\\:red_circle:" "🔴" julia-latexsubs)
+(puthash "\\:large_blue_circle:" "🔵" julia-latexsubs)
+(puthash "\\:large_orange_diamond:" "🔶" julia-latexsubs)
+(puthash "\\:large_blue_diamond:" "🔷" julia-latexsubs)
+(puthash "\\:small_orange_diamond:" "🔸" julia-latexsubs)
+(puthash "\\:small_blue_diamond:" "🔹" julia-latexsubs)
+(puthash "\\:small_red_triangle:" "🔺" julia-latexsubs)
+(puthash "\\:small_red_triangle_down:" "🔻" julia-latexsubs)
+(puthash "\\:arrow_up_small:" "🔼" julia-latexsubs)
+(puthash "\\:arrow_down_small:" "🔽" julia-latexsubs)
+(puthash "\\:clock1:" "🕐" julia-latexsubs)
+(puthash "\\:clock2:" "🕑" julia-latexsubs)
+(puthash "\\:clock3:" "🕒" julia-latexsubs)
+(puthash "\\:clock4:" "🕓" julia-latexsubs)
+(puthash "\\:clock5:" "🕔" julia-latexsubs)
+(puthash "\\:clock6:" "🕕" julia-latexsubs)
+(puthash "\\:clock7:" "🕖" julia-latexsubs)
+(puthash "\\:clock8:" "🕗" julia-latexsubs)
+(puthash "\\:clock9:" "🕘" julia-latexsubs)
+(puthash "\\:clock10:" "🕙" julia-latexsubs)
+(puthash "\\:clock11:" "🕚" julia-latexsubs)
+(puthash "\\:clock12:" "🕛" julia-latexsubs)
+(puthash "\\:clock130:" "🕜" julia-latexsubs)
+(puthash "\\:clock230:" "🕝" julia-latexsubs)
+(puthash "\\:clock330:" "🕞" julia-latexsubs)
+(puthash "\\:clock430:" "🕟" julia-latexsubs)
+(puthash "\\:clock530:" "🕠" julia-latexsubs)
+(puthash "\\:clock630:" "🕡" julia-latexsubs)
+(puthash "\\:clock730:" "🕢" julia-latexsubs)
+(puthash "\\:clock830:" "🕣" julia-latexsubs)
+(puthash "\\:clock930:" "🕤" julia-latexsubs)
+(puthash "\\:clock1030:" "🕥" julia-latexsubs)
+(puthash "\\:clock1130:" "🕦" julia-latexsubs)
+(puthash "\\:clock1230:" "🕧" julia-latexsubs)
+(puthash "\\:mount_fuji:" "🗻" julia-latexsubs)
+(puthash "\\:tokyo_tower:" "🗼" julia-latexsubs)
+(puthash "\\:statue_of_liberty:" "🗽" julia-latexsubs)
+(puthash "\\:japan:" "🗾" julia-latexsubs)
+(puthash "\\:moyai:" "🗿" julia-latexsubs)
+(puthash "\\:grinning:" "😀" julia-latexsubs)
+(puthash "\\:grin:" "😁" julia-latexsubs)
+(puthash "\\:joy:" "😂" julia-latexsubs)
+(puthash "\\:smiley:" "😃" julia-latexsubs)
+(puthash "\\:smile:" "😄" julia-latexsubs)
+(puthash "\\:sweat_smile:" "😅" julia-latexsubs)
+(puthash "\\:laughing:" "😆" julia-latexsubs)
+(puthash "\\:innocent:" "😇" julia-latexsubs)
+(puthash "\\:smiling_imp:" "😈" julia-latexsubs)
+(puthash "\\:wink:" "😉" julia-latexsubs)
+(puthash "\\:blush:" "😊" julia-latexsubs)
+(puthash "\\:yum:" "😋" julia-latexsubs)
+(puthash "\\:relieved:" "😌" julia-latexsubs)
+(puthash "\\:heart_eyes:" "😍" julia-latexsubs)
+(puthash "\\:sunglasses:" "😎" julia-latexsubs)
+(puthash "\\:smirk:" "😏" julia-latexsubs)
+(puthash "\\:neutral_face:" "😐" julia-latexsubs)
+(puthash "\\:expressionless:" "😑" julia-latexsubs)
+(puthash "\\:unamused:" "😒" julia-latexsubs)
+(puthash "\\:sweat:" "😓" julia-latexsubs)
+(puthash "\\:pensive:" "😔" julia-latexsubs)
+(puthash "\\:confused:" "😕" julia-latexsubs)
+(puthash "\\:confounded:" "😖" julia-latexsubs)
+(puthash "\\:kissing:" "😗" julia-latexsubs)
+(puthash "\\:kissing_heart:" "😘" julia-latexsubs)
+(puthash "\\:kissing_smiling_eyes:" "😙" julia-latexsubs)
+(puthash "\\:kissing_closed_eyes:" "😚" julia-latexsubs)
+(puthash "\\:stuck_out_tongue:" "😛" julia-latexsubs)
+(puthash "\\:stuck_out_tongue_winking_eye:" "😜" julia-latexsubs)
+(puthash "\\:stuck_out_tongue_closed_eyes:" "😝" julia-latexsubs)
+(puthash "\\:disappointed:" "😞" julia-latexsubs)
+(puthash "\\:worried:" "😟" julia-latexsubs)
+(puthash "\\:angry:" "😠" julia-latexsubs)
+(puthash "\\:rage:" "😡" julia-latexsubs)
+(puthash "\\:cry:" "😢" julia-latexsubs)
+(puthash "\\:persevere:" "😣" julia-latexsubs)
+(puthash "\\:triumph:" "😤" julia-latexsubs)
+(puthash "\\:disappointed_relieved:" "😥" julia-latexsubs)
+(puthash "\\:frowning:" "😦" julia-latexsubs)
+(puthash "\\:anguished:" "😧" julia-latexsubs)
+(puthash "\\:fearful:" "😨" julia-latexsubs)
+(puthash "\\:weary:" "😩" julia-latexsubs)
+(puthash "\\:sleepy:" "😪" julia-latexsubs)
+(puthash "\\:tired_face:" "😫" julia-latexsubs)
+(puthash "\\:grimacing:" "😬" julia-latexsubs)
+(puthash "\\:sob:" "😭" julia-latexsubs)
+(puthash "\\:open_mouth:" "😮" julia-latexsubs)
+(puthash "\\:hushed:" "😯" julia-latexsubs)
+(puthash "\\:cold_sweat:" "😰" julia-latexsubs)
+(puthash "\\:scream:" "😱" julia-latexsubs)
+(puthash "\\:astonished:" "😲" julia-latexsubs)
+(puthash "\\:flushed:" "😳" julia-latexsubs)
+(puthash "\\:sleeping:" "😴" julia-latexsubs)
+(puthash "\\:dizzy_face:" "😵" julia-latexsubs)
+(puthash "\\:no_mouth:" "😶" julia-latexsubs)
+(puthash "\\:mask:" "😷" julia-latexsubs)
+(puthash "\\:smile_cat:" "😸" julia-latexsubs)
+(puthash "\\:joy_cat:" "😹" julia-latexsubs)
+(puthash "\\:smiley_cat:" "😺" julia-latexsubs)
+(puthash "\\:heart_eyes_cat:" "😻" julia-latexsubs)
+(puthash "\\:smirk_cat:" "😼" julia-latexsubs)
+(puthash "\\:kissing_cat:" "😽" julia-latexsubs)
+(puthash "\\:pouting_cat:" "😾" julia-latexsubs)
+(puthash "\\:crying_cat_face:" "😿" julia-latexsubs)
+(puthash "\\:scream_cat:" "🙀" julia-latexsubs)
+(puthash "\\:no_good:" "🙅" julia-latexsubs)
+(puthash "\\:ok_woman:" "🙆" julia-latexsubs)
+(puthash "\\:bow:" "🙇" julia-latexsubs)
+(puthash "\\:see_no_evil:" "🙈" julia-latexsubs)
+(puthash "\\:hear_no_evil:" "🙉" julia-latexsubs)
+(puthash "\\:speak_no_evil:" "🙊" julia-latexsubs)
+(puthash "\\:raising_hand:" "🙋" julia-latexsubs)
+(puthash "\\:raised_hands:" "🙌" julia-latexsubs)
+(puthash "\\:person_frowning:" "🙍" julia-latexsubs)
+(puthash "\\:person_with_pouting_face:" "🙎" julia-latexsubs)
+(puthash "\\:pray:" "🙏" julia-latexsubs)
+(puthash "\\:rocket:" "🚀" julia-latexsubs)
+(puthash "\\:helicopter:" "🚁" julia-latexsubs)
+(puthash "\\:steam_locomotive:" "🚂" julia-latexsubs)
+(puthash "\\:railway_car:" "🚃" julia-latexsubs)
+(puthash "\\:bullettrain_side:" "🚄" julia-latexsubs)
+(puthash "\\:bullettrain_front:" "🚅" julia-latexsubs)
+(puthash "\\:train2:" "🚆" julia-latexsubs)
+(puthash "\\:metro:" "🚇" julia-latexsubs)
+(puthash "\\:light_rail:" "🚈" julia-latexsubs)
+(puthash "\\:station:" "🚉" julia-latexsubs)
+(puthash "\\:tram:" "🚊" julia-latexsubs)
+(puthash "\\:train:" "🚋" julia-latexsubs)
+(puthash "\\:bus:" "🚌" julia-latexsubs)
+(puthash "\\:oncoming_bus:" "🚍" julia-latexsubs)
+(puthash "\\:trolleybus:" "🚎" julia-latexsubs)
+(puthash "\\:busstop:" "🚏" julia-latexsubs)
+(puthash "\\:minibus:" "🚐" julia-latexsubs)
+(puthash "\\:ambulance:" "🚑" julia-latexsubs)
+(puthash "\\:fire_engine:" "🚒" julia-latexsubs)
+(puthash "\\:police_car:" "🚓" julia-latexsubs)
+(puthash "\\:oncoming_police_car:" "🚔" julia-latexsubs)
+(puthash "\\:taxi:" "🚕" julia-latexsubs)
+(puthash "\\:oncoming_taxi:" "🚖" julia-latexsubs)
+(puthash "\\:car:" "🚗" julia-latexsubs)
+(puthash "\\:oncoming_automobile:" "🚘" julia-latexsubs)
+(puthash "\\:blue_car:" "🚙" julia-latexsubs)
+(puthash "\\:truck:" "🚚" julia-latexsubs)
+(puthash "\\:articulated_lorry:" "🚛" julia-latexsubs)
+(puthash "\\:tractor:" "🚜" julia-latexsubs)
+(puthash "\\:monorail:" "🚝" julia-latexsubs)
+(puthash "\\:mountain_railway:" "🚞" julia-latexsubs)
+(puthash "\\:suspension_railway:" "🚟" julia-latexsubs)
+(puthash "\\:mountain_cableway:" "🚠" julia-latexsubs)
+(puthash "\\:aerial_tramway:" "🚡" julia-latexsubs)
+(puthash "\\:ship:" "🚢" julia-latexsubs)
+(puthash "\\:rowboat:" "🚣" julia-latexsubs)
+(puthash "\\:speedboat:" "🚤" julia-latexsubs)
+(puthash "\\:traffic_light:" "🚥" julia-latexsubs)
+(puthash "\\:vertical_traffic_light:" "🚦" julia-latexsubs)
+(puthash "\\:construction:" "🚧" julia-latexsubs)
+(puthash "\\:rotating_light:" "🚨" julia-latexsubs)
+(puthash "\\:triangular_flag_on_post:" "🚩" julia-latexsubs)
+(puthash "\\:door:" "🚪" julia-latexsubs)
+(puthash "\\:no_entry_sign:" "🚫" julia-latexsubs)
+(puthash "\\:smoking:" "🚬" julia-latexsubs)
+(puthash "\\:no_smoking:" "🚭" julia-latexsubs)
+(puthash "\\:put_litter_in_its_place:" "🚮" julia-latexsubs)
+(puthash "\\:do_not_litter:" "🚯" julia-latexsubs)
+(puthash "\\:potable_water:" "🚰" julia-latexsubs)
+(puthash "\\:non-potable_water:" "🚱" julia-latexsubs)
+(puthash "\\:bike:" "🚲" julia-latexsubs)
+(puthash "\\:no_bicycles:" "🚳" julia-latexsubs)
+(puthash "\\:bicyclist:" "🚴" julia-latexsubs)
+(puthash "\\:mountain_bicyclist:" "🚵" julia-latexsubs)
+(puthash "\\:walking:" "🚶" julia-latexsubs)
+(puthash "\\:no_pedestrians:" "🚷" julia-latexsubs)
+(puthash "\\:children_crossing:" "🚸" julia-latexsubs)
+(puthash "\\:mens:" "🚹" julia-latexsubs)
+(puthash "\\:womens:" "🚺" julia-latexsubs)
+(puthash "\\:restroom:" "🚻" julia-latexsubs)
+(puthash "\\:baby_symbol:" "🚼" julia-latexsubs)
+(puthash "\\:toilet:" "🚽" julia-latexsubs)
+(puthash "\\:wc:" "🚾" julia-latexsubs)
+(puthash "\\:shower:" "🚿" julia-latexsubs)
+(puthash "\\:bath:" "🛀" julia-latexsubs)
+(puthash "\\:bathtub:" "🛁" julia-latexsubs)
+(puthash "\\:passport_control:" "🛂" julia-latexsubs)
+(puthash "\\:customs:" "🛃" julia-latexsubs)
+(puthash "\\:baggage_claim:" "🛄" julia-latexsubs)
+(puthash "\\:left_luggage:" "🛅" julia-latexsubs)
diff --git a/elpa/julia-mode-20191002.1352/julia-mode-autoloads.el b/elpa/julia-mode-20191002.1352/julia-mode-autoloads.el
new file mode 100644 (file)
index 0000000..268089a
--- /dev/null
@@ -0,0 +1,37 @@
+;;; julia-mode-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
+\f
+;;;### (autoloads nil "julia-mode" "julia-mode.el" (23997 31535 905690
+;;;;;;  231000))
+;;; Generated autoloads from julia-mode.el
+
+(add-to-list 'auto-mode-alist '("\\.jl\\'" . julia-mode))
+
+(autoload 'julia-mode "julia-mode" "\
+Major mode for editing julia code.
+
+\(fn)" t nil)
+
+(autoload 'inferior-julia "julia-mode" "\
+Run an inferior instance of `julia' inside Emacs.
+
+\(fn)" t nil)
+
+(defalias 'run-julia #'inferior-julia "\
+Run an inferior instance of `julia' inside Emacs.")
+
+;;;***
+\f
+;;;### (autoloads nil nil ("julia-latexsubs.el" "julia-mode-pkg.el")
+;;;;;;  (23997 31535 909479 733000))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+;;; julia-mode-autoloads.el ends here
diff --git a/elpa/julia-mode-20191002.1352/julia-mode-pkg.el b/elpa/julia-mode-20191002.1352/julia-mode-pkg.el
new file mode 100644 (file)
index 0000000..66c59f6
--- /dev/null
@@ -0,0 +1,6 @@
+(define-package "julia-mode" "20191002.1352" "Major mode for editing Julia source code" 'nil :keywords
+  '("languages")
+  :url "https://github.com/JuliaLang/julia")
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
diff --git a/elpa/julia-mode-20191002.1352/julia-mode.el b/elpa/julia-mode-20191002.1352/julia-mode.el
new file mode 100644 (file)
index 0000000..3263507
--- /dev/null
@@ -0,0 +1,946 @@
+;;; julia-mode.el --- Major mode for editing Julia source code
+
+;; Copyright (C) 2009-2014 Julia contributors
+;; URL: https://github.com/JuliaLang/julia
+;; Version: 0.3
+;; Keywords: languages
+
+;;; Usage:
+;; Put the following code in your .emacs, site-load.el, or other relevant file
+;; (add-to-list 'load-path "path-to-julia-mode")
+;; (require 'julia-mode)
+
+;;; Commentary:
+;; This is the official Emacs mode for editing Julia programs.
+
+;;; License:
+;; Permission is hereby granted, free of charge, to any person obtaining
+;; a copy of this software and associated documentation files (the
+;; "Software"), to deal in the Software without restriction, including
+;; without limitation the rights to use, copy, modify, merge, publish,
+;; distribute, sublicense, and/or sell copies of the Software, and to
+;; permit persons to whom the Software is furnished to do so, subject to
+;; the following conditions:
+;;
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+;;
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+;; WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+;;; Code:
+
+;; We can't use cl-lib whilst supporting Emacs 23 users who don't use
+;; ELPA.
+(with-no-warnings
+  (require 'cl)) ;; incf, decf, plusp
+
+(defvar julia-mode-hook nil)
+
+(defgroup julia ()
+  "Major mode for the julia programming language."
+  :group 'languages
+  :prefix "julia-")
+
+(defcustom julia-indent-offset 4
+  "Number of spaces per indentation level."
+  :type 'integer
+  :group 'julia)
+
+(defface julia-macro-face
+  '((t :inherit font-lock-preprocessor-face))
+  "Face for Julia macro invocations."
+  :group 'julia-mode)
+
+(defface julia-quoted-symbol-face
+  '((t :inherit font-lock-preprocessor-face))
+  "Face for quoted Julia symbols, e.g. :foo."
+  :group 'julia-mode)
+
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.jl\\'" . julia-mode))
+
+;; define ignore-errors macro if it isn't present
+;; (necessary for emacs 22 compatibility)
+(when (not (fboundp 'ignore-errors))
+  (defmacro ignore-errors (body) `(condition-case nil ,body (error nil))))
+
+(defun julia--regexp-opt (strings &optional paren)
+  "Emacs 23 provides `regexp-opt', but it does not support PAREN taking the value 'symbols.
+This function provides equivalent functionality, but makes no efforts to optimise the regexp."
+  (cond
+   ((>= emacs-major-version 24)
+    (regexp-opt strings paren))
+   ((not (eq paren 'symbols))
+    (regexp-opt strings paren))
+   ((null strings)
+    "")
+   ('t
+    (rx-to-string `(seq symbol-start (or ,@strings) symbol-end)))))
+
+(defvar julia-mode-syntax-table
+  (let ((table (make-syntax-table)))
+    (modify-syntax-entry ?_ "_" table)
+    (modify-syntax-entry ?@ "_" table)
+    (modify-syntax-entry ?! "_" table)
+    (modify-syntax-entry ?# "< 14" table)  ; # single-line and multiline start
+    (modify-syntax-entry ?= ". 23bn" table)
+    (modify-syntax-entry ?\n ">" table)  ; \n single-line comment end
+    (modify-syntax-entry ?\{ "(} " table)
+    (modify-syntax-entry ?\} "){ " table)
+    (modify-syntax-entry ?\[ "(] " table)
+    (modify-syntax-entry ?\] ")[ " table)
+    (modify-syntax-entry ?\( "() " table)
+    (modify-syntax-entry ?\) ")( " table)
+    ;; Here, we treat ' as punctuation (when it's used for transpose),
+    ;; see our use of `julia-char-regex' for handling ' as a character
+    ;; delimiter
+    (modify-syntax-entry ?'  "." table)
+    (modify-syntax-entry ?\" "\"" table)
+    (modify-syntax-entry ?` "\"" table)
+    (modify-syntax-entry ?\\ "\\" table)
+
+    (modify-syntax-entry ?. "." table)
+    (modify-syntax-entry ?? "." table)
+    (modify-syntax-entry ?$ "." table)
+    (modify-syntax-entry ?& "." table)
+    (modify-syntax-entry ?* "." table)
+    (modify-syntax-entry ?/ "." table)
+    (modify-syntax-entry ?+ "." table)
+    (modify-syntax-entry ?- "." table)
+    (modify-syntax-entry ?< "." table)
+    (modify-syntax-entry ?> "." table)
+    (modify-syntax-entry ?% "." table)
+
+    (modify-syntax-entry ?′ "w" table) ; \prime is a word constituent
+    table)
+  "Syntax table for `julia-mode'.")
+
+(eval-when-compile
+  (defconst julia-char-regex
+    (rx (or (any "-" ";" "\\" "^" "!" "|" "?" "*" "<" "%" "," "=" ">" "+" "/" "&" "$" "~" ":")
+            (syntax open-parenthesis)
+            (syntax whitespace)
+            bol)
+        (group "'")
+        (group
+         (or (repeat 0 8 (not (any "'"))) (not (any "\\"))
+             "\\\\"))
+        (group "'"))))
+
+(defconst julia-hanging-operator-regexp
+  ;; taken from julia-parser.scm
+  (concat "^[^#\n]+ "
+          (regexp-opt
+           '( ;; conditional
+             "?"
+             ;; assignment
+             "=" ":=" "+=" "-=" "*=" "/=" "//=" ".//=" ".*=" "./=" "\\=" ".\\="
+             "^=" ".^=" "÷=" ".÷=" "%=" ".%=" "|=" "&=" "$=" "=>" "<<=" ">>="
+             ">>>=" "~" ".+=" ".-="
+             ;; arrow
+             "--" "-->" "←" "→" "↔" "↚" "↛" "↠" "↣" "↦" "↮" "⇎" "⇏" "⇒" "⇔" "⇴"
+             "⇶" "⇷" "⇸" "⇹" "⇺" "⇻" "⇼" "⇽" "⇾" "⇿" "⟵" "⟶" "⟷" "⟷" "⟹"
+             "⟺" "⟻" "⟼" "⟽" "⟾" "⟿" "⤀" "⤁" "⤂" "⤃" "⤄" "⤅" "⤆" "⤇" "⤌"
+             "⤍" "⤎" "⤏" "⤐" "⤑" "⤔" "⤕" "⤖" "⤗" "⤘" "⤝" "⤞" "⤟" "⤠" "⥄" "⥅"
+             "⥆" "⥇" "⥈" "⥊" "⥋" "⥎" "⥐" "⥒" "⥓" "⥖" "⥗" "⥚" "⥛" "⥞" "⥟" "⥢"
+             "⥤" "⥦" "⥧" "⥨" "⥩" "⥪" "⥫" "⥬" "⥭" "⥰" "⧴" "⬱" "⬰" "⬲" "⬳" "⬴"
+             "⬵" "⬶" "⬷" "⬸" "⬹" "⬺" "⬻" "⬼" "⬽" "⬾" "⬿" "⭀" "⭁" "⭂" "⭃" "⭄"
+             "⭇" "⭈" "⭉" "⭊" "⭋" "⭌" "←" "→"
+             ;; or and and
+             "&&" "||"
+             ;; comparison
+             ">" "<" ">=" "≥" "<=" "≤" "==" "===" "≡" "!=" "≠" "!==" "≢" ".>"
+             ".<" ".>=" ".≥" ".<=" ".≤" ".==" ".!=" ".≠" ".=" ".!" "<:" ">:" "∈"
+             "∉" "∋" "∌" "⊆" "⊈" "⊂" "⊄" "⊊" "∝" "∊" "∍" "∥" "∦" "∷" "∺" "∻" "∽"
+             "∾" "≁" "≃" "≄" "≅" "≆" "≇" "≈" "≉" "≊" "≋" "≌" "≍" "≎" "≐" "≑" "≒"
+             "≓" "≔" "≕" "≖" "≗" "≘" "≙" "≚" "≛" "≜" "≝" "≞" "≟" "≣" "≦" "≧" "≨"
+             "≩" "≪" "≫" "≬" "≭" "≮" "≯" "≰" "≱" "≲" "≳" "≴" "≵" "≶" "≷" "≸" "≹"
+             "≺" "≻" "≼" "≽" "≾" "≿" "⊀" "⊁" "⊃" "⊅" "⊇" "⊉" "⊋" "⊏" "⊐" "⊑" "⊒"
+             "⊜" "⊩" "⊬" "⊮" "⊰" "⊱" "⊲" "⊳" "⊴" "⊵" "⊶" "⊷" "⋍" "⋐" "⋑" "⋕" "⋖"
+             "⋗" "⋘" "⋙" "⋚" "⋛" "⋜" "⋝" "⋞" "⋟" "⋠" "⋡" "⋢" "⋣" "⋤" "⋥" "⋦" "⋧"
+             "⋨" "⋩" "⋪" "⋫" "⋬" "⋭" "⋲" "⋳" "⋴" "⋵" "⋶" "⋷" "⋸" "⋹" "⋺" "⋻" "⋼"
+             "⋽" "⋾" "⋿" "⟈" "⟉" "⟒" "⦷" "⧀" "⧁" "⧡" "⧣" "⧤" "⧥" "⩦" "⩧" "⩪" "⩫"
+             "⩬" "⩭" "⩮" "⩯" "⩰" "⩱" "⩲" "⩳" "⩴" "⩵" "⩶" "⩷" "⩸" "⩹" "⩺" "⩻" "⩼"
+             "⩽" "⩾" "⩿" "⪀" "⪁" "⪂" "⪃" "⪄" "⪅" "⪆" "⪇" "⪈" "⪉" "⪊" "⪋" "⪌" "⪍"
+             "⪎" "⪏" "⪐" "⪑" "⪒" "⪓" "⪔" "⪕" "⪖" "⪗" "⪘" "⪙" "⪚" "⪛" "⪜" "⪝" "⪞"
+             "⪟" "⪠" "⪡" "⪢" "⪣" "⪤" "⪥" "⪦" "⪧" "⪨" "⪩" "⪪" "⪫" "⪬" "⪭" "⪮" "⪯"
+             "⪰" "⪱" "⪲" "⪳" "⪴" "⪵" "⪶" "⪷" "⪸" "⪹" "⪺" "⪻" "⪼" "⪽" "⪾" "⪿" "⫀"
+             "⫁" "⫂" "⫃" "⫄" "⫅" "⫆" "⫇" "⫈" "⫉" "⫊" "⫋" "⫌" "⫍" "⫎" "⫏" "⫐" "⫑"
+             "⫒" "⫓" "⫔" "⫕" "⫖" "⫗" "⫘" "⫙" "⫷" "⫸" "⫹" "⫺" "⊢" "⊣"
+             ;; pipe, colon
+             "|>" "<|" ":" ".."
+             ;; plus
+             "+" "-" "⊕" "⊖" "⊞" "⊟" ".+" ".-" "++" "|" "∪" "∨" "$" "⊔" "±" "∓"
+             "∔" "∸" "≂" "≏" "⊎" "⊻" "⊽" "⋎" "⋓" "⧺" "⧻" "⨈" "⨢" "⨣" "⨤" "⨥" "⨦"
+             "⨧" "⨨" "⨩" "⨪" "⨫" "⨬" "⨭" "⨮" "⨹" "⨺" "⩁" "⩂" "⩅" "⩊" "⩌" "⩏" "⩐"
+             "⩒" "⩔" "⩖" "⩗" "⩛" "⩝" "⩡" "⩢" "⩣"
+             ;; bitshift
+             "<<" ">>" ">>>" ".<<" ".>>" ".>>>"
+             ;; times
+             "*" "/" "./" "÷" ".÷" "%" "⋅" "∘" "×" ".%" ".*" "\\"
+             ".\\" "&" "∩" "∧" "⊗" "⊘" "⊙" "⊚" "⊛" "⊠" "⊡" "⊓" "∗" "∙" "∤" "⅋"
+             "≀" "⊼" "⋄" "⋆" "⋇" "⋉" "⋊" "⋋" "⋌" "⋏" "⋒" "⟑" "⦸" "⦼" "⦾" "⦿" "⧶"
+             "⧷" "⨇" "⨰" "⨱" "⨲" "⨳" "⨴" "⨵" "⨶" "⨷" "⨸" "⨻" "⨼" "⨽" "⩀" "⩃" "⩄"
+             "⩋" "⩍" "⩎" "⩑" "⩓" "⩕" "⩘" "⩚" "⩜" "⩞" "⩟" "⩠" "⫛" "⊍" "▷" "⨝" "⟕"
+             "⟖" "⟗"
+             ;; rational
+             "//" ".//"
+             ;; power
+             "^" ".^" "↑" "↓" "⇵" "⟰" "⟱" "⤈" "⤉" "⤊" "⤋" "⤒" "⤓" "⥉" "⥌" "⥍"
+             "⥏" "⥑" "⥔" "⥕" "⥘" "⥙" "⥜" "⥝" "⥠" "⥡" "⥣" "⥥" "⥮" "⥯" "↑" "↓"
+             ;; decl, dot
+             "::" "."))
+          (regexp-opt '(" #" " \n" "#" "\n"))))
+
+(defconst julia-triple-quoted-string-regex
+  ;; We deliberately put a group on the first and last delimiter, so
+  ;; we can mark these as string delimiters for font-lock.
+  (rx (group "\"")
+      (group "\"\""
+             ;; After the delimiter, we're a sequence of
+             ;; non-backslashes or blackslashes paired with something.
+             (*? (or (not (any "\\"))
+                     (seq "\\" anything)))
+             "\"\"")
+      (group "\"")))
+
+(defconst julia-unquote-regex
+  "\\(\\s(\\|\\s-\\|-\\|[,%=<>\\+*/?&|!\\^~\\\\;:]\\|^\\)\\($[a-zA-Z0-9_]+\\)")
+
+(defconst julia-forloop-in-regex
+  "for +.*[^
+].* \\(in\\)\\(\\s-\\|$\\)+")
+
+(defconst julia-function-regex
+  (rx line-start (* (or space "@inline" "@noinline")) symbol-start
+      "function"
+      (1+ space)
+      ;; Don't highlight module names in function declarations:
+      (* (seq (1+ (or word (syntax symbol))) "."))
+      ;; The function name itself
+      (group (1+ (or word (syntax symbol))))))
+
+(defconst julia-function-assignment-regex
+  (rx line-start (* (or space "@inline" "@noinline")) symbol-start
+      (* (seq (1+ (or word (syntax symbol))) ".")) ; module name
+      (group (1+ (or word (syntax symbol))))
+      (? "{" (* (not (any "}"))) "}")
+      "(" (* (or
+              (seq "(" (* (not (any "(" ")"))) ")")
+              (not (any "(" ")"))))
+      ")"
+      (* space)
+      (? "::" (* space) (1+ (not (any space))))
+      (* space)
+      (* (seq "where" (or "{" (+ space)) (+ (not (any "=")))))
+      "="
+      (not (any "="))))
+
+(defconst julia-type-regex
+  (rx symbol-start (or ;;"immutable" "type" ;; remove after 0.6
+                       "abstract type" "primitive type" "struct" "mutable struct")
+      (1+ space) (group (1+ (or word (syntax symbol))))))
+
+(defconst julia-type-annotation-regex
+  (rx "::" (0+ space) (group (1+ (or word (syntax symbol))))))
+
+;;(defconst julia-type-parameter-regex
+;;  (rx symbol-start (1+ (or (or word (syntax symbol)) ?_)) "{" (group (1+ (or (or word (syntax symbol)) ?_))) "}"))
+
+(defconst julia-subtype-regex
+  (rx "<:" (0+ space) (group (1+ (or word (syntax symbol)))) (0+ space) (or "\n" "{" "}" "end")))
+
+(defconst julia-macro-regex
+  (rx symbol-start (group "@" (1+ (or word (syntax symbol))))))
+
+(defconst julia-keyword-regex
+  (julia--regexp-opt
+   '("if" "else" "elseif" "while" "for" "begin" "end" "quote"
+     "try" "catch" "return" "local" "function" "macro" "ccall"
+     "finally" "break" "continue" "global" "where"
+     "module" "using" "import" "export" "const" "let" "do" "in"
+     "baremodule"
+     ;; "importall" ;; deprecated in 0.7
+     ;; "immutable" "type" "bitstype" "abstract" "typealias" ;; removed in 1.0
+     "abstract type" "primitive type" "struct" "mutable struct")
+   'symbols))
+
+(defconst julia-builtin-regex
+  (julia--regexp-opt
+   ;;'("error" "throw")
+   '()
+   'symbols))
+
+(defconst julia-builtin-types-regex
+  (julia--regexp-opt
+   '("Number" "Real" "BigInt" "Integer"
+     "UInt" "UInt8" "UInt16" "UInt32" "UInt64" "UInt128"
+     "Int" "Int8" "Int16" "Int32" "Int64" "Int128"
+     "BigFloat" "AbstractFloat" "Float16" "Float32" "Float64"
+     ;;"Complex128" "Complex64" ;; replaced in 1.0
+     "ComplexF32" "ComplexF64"
+     "Bool"
+     "Cuchar" "Cshort" "Cushort" "Cint" "Cuint" "Clonglong" "Culonglong" "Cintmax_t" "Cuintmax_t"
+     "Cfloat" "Cdouble" "Cptrdiff_t" "Cssize_t" "Csize_t"
+     "Cchar" "Clong" "Culong" "Cwchar_t" "Cvoid"
+     "Cstring" "Cwstring" ;; C strings made of ordinary and wide characters
+     "Char" "String" "SubString"
+     "Array" "DArray" "AbstractArray" "AbstractVector" "AbstractMatrix" "AbstractSparseMatrix" "SubArray" "StridedArray" "StridedVector" "StridedMatrix" "VecOrMat" "StridedVecOrMat" "DenseArray" "SparseMatrixCSC" "BitArray"
+     "AbstractRange" "OrdinalRange" "StepRange" "UnitRange" "FloatRange"
+     "Tuple" "NTuple" "Vararg"
+     "DataType" "Symbol" "Function" "Vector" "Matrix" "Union" "Type" "Any" "Complex" "AbstractString" "Ptr" "Nothing" "Exception" "Task" "Signed" "Unsigned" "AbstractDict" "Dict" "IO" "IOStream" "Rational" "Regex" "RegexMatch" "Set" "BitSet" "Expr" "WeakRef" "ObjectIdDict"
+     "AbstractRNG" "MersenneTwister"
+     )
+   'symbols))
+
+(defconst julia-quoted-symbol-regex
+  ;; :foo and :foo2 are valid, but :123 is not.
+  (rx (or bol whitespace "(" "[" "," "=")
+      (group ":" (or letter (syntax symbol)) (0+ (or word (syntax symbol))))))
+
+(defconst julia-font-lock-keywords
+  (list
+   ;; Ensure :: and <: aren't highlighted, so we don't confuse ::Foo with :foo.
+   ;; (in Emacs, keywords don't overlap).
+   (cons (rx (or "::" "<:")) ''default)
+   ;; Highlight quoted symbols before keywords, so :function is not
+   ;; highlighted as a keyword.
+   (list julia-quoted-symbol-regex 1 ''julia-quoted-symbol-face)
+   (cons julia-builtin-types-regex 'font-lock-type-face)
+   (cons julia-keyword-regex 'font-lock-keyword-face)
+   (cons julia-macro-regex ''julia-macro-face)
+   (cons
+    (julia--regexp-opt
+     '("true" "false" "C_NULL" "Inf" "NaN" "Inf32" "NaN32" "nothing" "undef")
+     'symbols)
+    'font-lock-constant-face)
+   (list julia-unquote-regex 2 'font-lock-constant-face)
+   (list julia-forloop-in-regex 1 'font-lock-keyword-face)
+   (list julia-function-regex 1 'font-lock-function-name-face)
+   (list julia-function-assignment-regex 1 'font-lock-function-name-face)
+   (list julia-type-regex 1 'font-lock-type-face)
+   (list julia-type-annotation-regex 1 'font-lock-type-face)
+   ;;(list julia-type-parameter-regex 1 'font-lock-type-face)
+   (list julia-subtype-regex 1 'font-lock-type-face)
+   (list julia-builtin-regex 1 'font-lock-builtin-face)
+   ))
+
+(defconst julia-block-start-keywords
+  (list "if" "while" "for" "begin" "try" "function" "let" "macro"
+        "quote" "do" "module"
+        ;; "immutable" "type" ;; remove after 0.6
+        "abstract type" "primitive type" "struct" "mutable struct"))
+
+;; For keywords that begin a block without additional indentation
+(defconst julia-block-start-keywords-no-indent
+  (list "module"))
+
+(defconst julia-block-end-keywords
+  (list "end" "else" "elseif" "catch" "finally"))
+
+(defun julia-stringify-triple-quote ()
+  "Put `syntax-table' property on triple-quoted string delimiters.
+
+Based on `python-syntax-stringify'."
+  (let* ((string-start-pos (- (point) 3))
+         (string-end-pos (point))
+         (ppss (prog2
+                   (backward-char 3)
+                   (syntax-ppss)
+                 (forward-char 3)))
+         (in-comment (nth 4 ppss))
+         (in-string (nth 8 ppss)))
+    (unless in-comment
+      (if in-string
+          ;; We're in a string, so this must be the closing triple-quote.
+          ;; Put | on the last " character.
+          (put-text-property (1- string-end-pos) string-end-pos
+                             'syntax-table (string-to-syntax "|"))
+        ;; We're not in a string, so this is the opening triple-quote.
+        ;; Put | on the first " character.
+        (put-text-property string-start-pos (1+ string-start-pos)
+                           'syntax-table (string-to-syntax "|"))))))
+
+(defconst julia-syntax-propertize-function
+  (unless (< emacs-major-version 24)
+    (syntax-propertize-rules
+     ("\"\"\""
+      (0 (ignore (julia-stringify-triple-quote))))
+     (julia-char-regex
+      (1 "\"")                 ; Treat ' as a string delimiter.
+      (2 ".")                  ; Don't highlight anything between.
+      (3 "\""))))) ; Treat the last " in """ as a string delimiter.
+
+(defun julia-in-comment (&optional syntax-ppss)
+  "Return non-nil if point is inside a comment using SYNTAX-PPSS.
+Handles both single-line and multi-line comments."
+  (nth 4 (or syntax-ppss (syntax-ppss))))
+
+(defun julia-in-string (&optional syntax-ppss)
+  "Return non-nil if point is inside a string using SYNTAX-PPSS.
+Note this is Emacs' notion of what is highlighted as a string.
+As a result, it is true inside \"foo\", `foo` and 'f'."
+  (nth 3 (or syntax-ppss (syntax-ppss))))
+
+(defun julia-in-brackets ()
+  "Return non-nil if point is inside square brackets."
+  (let ((start-pos (point))
+        (open-count 0))
+    ;; Count all the [ and ] characters on the current line.
+    (save-excursion
+      (beginning-of-line)
+
+      (while (< (point) start-pos)
+        ;; Don't count [ or ] inside strings, characters or comments.
+        (unless (or (julia-in-string) (julia-in-comment))
+
+          (when (looking-at (rx "["))
+            (incf open-count))
+          (when (looking-at (rx "]"))
+            (decf open-count)))
+
+        (forward-char 1)))
+
+    ;; If we've opened more than we've closed, we're inside brackets.
+    (plusp open-count)))
+
+(defun julia-at-keyword (kw-list)
+  "Return the word at point if it matches any keyword in KW-LIST.
+KW-LIST is a list of strings.  The word at point is not considered
+a keyword if used as a field name, X.word, or quoted, :word."
+  (and (or (= (point) 1)
+          (and (not (equal (char-before (point)) ?.))
+               (not (equal (char-before (point)) ?:))))
+       (not (looking-at "("))           ; handle "function(" when on (
+       (member (current-word t) kw-list)
+       ;; 'end' is not a keyword when used for indexing, e.g. foo[end-2]
+       (or (not (equal (current-word t) "end"))
+           (not (julia-in-brackets)))
+       (not (julia-in-comment))))
+
+;; if backward-sexp gives an error, move back 1 char to move over the '('
+(defun julia-safe-backward-sexp ()
+  (if (condition-case nil (backward-sexp) (error t))
+      (ignore-errors (backward-char))))
+
+(defun julia-following-import-export-using ()
+  "If the current line follows an `export` or `import` keyword
+with valid syntax, return the position of the keyword, otherwise
+`nil`. Works by stepping backwards through comma-separated
+symbol, gives up when this is not true."
+  ;; Implementation accepts a single Module: right after the keyword, and saves
+  ;; the module name for future use, but does not enforce that `export` has no
+  ;; module name.
+  (let ((done nil)                      ; find keyword or give up
+        (module nil))                   ; found "Module:"
+    (save-excursion
+      (beginning-of-line)
+      (while (and (not done) (< (point-min) (point)))
+        (julia-safe-backward-sexp)
+        (cond
+         ((looking-at (rx (or "import" "export" "using")))
+          (setf done (point)))
+         ((looking-at (rx (group (* (or word (syntax symbol)))) (0+ space) ":"))
+          (if module
+              (setf done 'broken)
+            (setf module (match-string-no-properties 1))))
+         ((looking-at (rx (* (or word (syntax symbol))) (0+ space) ","))
+          (when module (setf done 'broken)))
+         (t (setf done 'broken)))))
+    (if (eq done 'broken)
+        nil
+      done)))
+
+(defun julia-last-open-block-pos (min)
+  "Return the position of the last open block, if one found.
+Do not move back beyond position MIN."
+  (save-excursion
+    (let ((count 0))
+      (while (not (or (> count 0) (<= (point) min)))
+        (julia-safe-backward-sexp)
+        (setq count
+              (cond ((julia-at-keyword julia-block-start-keywords)
+                     (+ count 1))
+                    ((and (equal (current-word t) "end")
+                          (not (julia-in-comment)))
+                     (- count 1))
+                    (t count))))
+      (if (> count 0)
+          (point)
+        nil))))
+
+(defun julia-last-open-block (min)
+  "Move back and return indentation level for last open block.
+Do not move back beyond MIN."
+  ;; Ensure MIN is not before the start of the buffer.
+  (setq min (max min (point-min)))
+  (let ((pos (julia-last-open-block-pos min)))
+    (and pos
+        (progn
+          (goto-char pos)
+          (+ julia-indent-offset (current-indentation))))))
+
+(defsubst julia--safe-backward-char ()
+  "Move back one character, but don't error if we're at the
+beginning of the buffer."
+  (unless (eq (point) (point-min))
+    (backward-char)))
+
+(defcustom julia-max-block-lookback 5000
+  "When indenting, don't look back more than this
+many characters to see if there are unclosed blocks.
+
+This variable has a moderate effect on indent performance if set too
+high, but stops indenting in the middle of long blocks if set too low."
+  :type 'integer
+  :group 'julia)
+
+(defun julia-paren-indent ()
+  "Return the column of the text following the innermost
+containing paren before point, so we can align succeeding code
+with it. Returns nil if we're not within nested parens."
+  (save-excursion
+    (beginning-of-line)
+    (let ((parser-state (syntax-ppss)))
+      (cond ((nth 3 parser-state) nil)       ;; strings
+            ((= (nth 0 parser-state) 0) nil) ;; top level
+            (t
+             (ignore-errors ;; return nil if any of these movements fail
+               (beginning-of-line)
+               (skip-syntax-forward " ")
+               (let ((possibly-close-paren-point (point)))
+                 (backward-up-list)
+                 (let ((open-paren-point (point)))
+                   (forward-char)
+                   (skip-syntax-forward " ")
+                   (if (eolp)
+                       (progn
+                         (up-list)
+                         (backward-char)
+                         (let ((paren-closed (= (point) possibly-close-paren-point)))
+                           (goto-char open-paren-point)
+                           (beginning-of-line)
+                           (skip-syntax-forward " ")
+                           (+ (current-column)
+                              (if paren-closed
+                                  0
+                                julia-indent-offset))))
+                     (current-column))))))))))
+
+(defun julia-prev-line-skip-blank-or-comment ()
+  "Move point to beginning of previous line skipping blank lines
+and lines including only comments. Returns number of lines moved.
+A return of -1 signals that we moved to the first line of
+the (possibly narrowed) buffer, so there is nowhere else to go."
+  (catch 'result
+    (let ((moved 0) this-move)
+      (while t
+        (setq this-move (forward-line -1))
+        (cond
+         ;; moved into comment or blank
+         ((and (= 0 this-move)
+               (or (looking-at-p "^\\s-*\\(?:#.*\\)*$")
+                   (julia-in-comment)))
+          (incf moved))
+         ;; success
+         ((= 0 this-move)
+          (throw 'result (1+ moved)))
+         ;; on first line and in comment
+         ((and (bobp)
+               (or (looking-at-p "^\\s-*\\(?:#.*\\)*$")
+                   (julia-in-comment)))
+          (throw 'result -1))
+         ((bobp)
+          (throw 'result moved))
+         (t
+          (throw 'result 0)))))))
+
+(defun julia-indent-hanging ()
+  "Calculate indentation for lines that follow \"hanging\"
+operators (operators that end the previous line) as defined in
+`julia-hanging-operator-regexp'. An assignment operator ending
+the previous line increases the indent as do the other operators
+unless another operator is found two lines up. Previous line
+means previous line after skipping blank lines and lines with
+only comments."
+  (let (prev-indent)
+    (save-excursion
+      (when (> (julia-prev-line-skip-blank-or-comment) 0)
+        (setq prev-indent (current-indentation))
+        (when (looking-at-p julia-hanging-operator-regexp)
+          (if (and (> (julia-prev-line-skip-blank-or-comment) 0)
+                   (looking-at-p julia-hanging-operator-regexp))
+              ;; two preceding hanging operators => indent same as line
+              ;; above
+              prev-indent
+            ;; one preceding hanging operator => increase indent from line
+            ;; above
+            (+ julia-indent-offset prev-indent)))))))
+
+(defun julia-indent-in-string ()
+  "Indentation inside strings with newlines is \"manual\",
+meaning always increase indent on TAB and decrease on S-TAB."
+  (save-excursion
+    (beginning-of-line)
+    (when (julia-in-string)
+      (if (member this-command '(julia-latexsub-or-indent
+                                 ess-indent-or-complete))
+          (+ julia-indent-offset (current-indentation))
+        ;; return the current indentation to prevent other functions from
+        ;; indenting inside strings
+        (current-indentation)))))
+
+(defun julia-indent-import-export-using ()
+  "Indent offset for lines that follow `import` or `export`, otherwise nil."
+  (when (julia-following-import-export-using)
+    julia-indent-offset))
+
+(defun julia-indent-line ()
+  "Indent current line of julia code."
+  (interactive)
+  (let* ((point-offset (- (current-column) (current-indentation))))
+    (indent-line-to
+     (or
+      ;; note: if this first function returns nil the beginning of the line
+      ;; cannot be in a string
+      (julia-indent-in-string)
+      ;; If we're inside an open paren, indent to line up arguments. After this,
+      ;; we cannot be inside parens which includes brackets
+      (julia-paren-indent)
+      ;; indent due to hanging operators (lines ending in an operator)
+      (julia-indent-hanging)
+      ;; indent for import and export
+      (julia-indent-import-export-using)
+      ;; Indent according to how many nested blocks we are in.
+      (save-excursion
+        (beginning-of-line)
+        ;; jump out of any comments
+        (let ((state (syntax-ppss)))
+          (when (nth 4 state)
+            (goto-char (nth 8 state))))
+        (forward-to-indentation 0)
+        (let ((endtok (julia-at-keyword julia-block-end-keywords))
+              (last-open-block (julia-last-open-block (- (point) julia-max-block-lookback))))
+          (max 0 (+ (or last-open-block 0)
+                    (if (or endtok
+                            (julia-at-keyword julia-block-start-keywords-no-indent))
+                        (- julia-indent-offset) 0)))))))
+    ;; Point is now at the beginning of indentation, restore it
+    ;; to its original position (relative to indentation).
+    (when (>= point-offset 0)
+      (move-to-column (+ (current-indentation) point-offset)))))
+
+(defalias 'julia-mode-prog-mode
+  (if (fboundp 'prog-mode)
+      'prog-mode
+    'fundamental-mode))
+
+\f
+;;; Navigation
+;; based off python.el
+(defconst julia-beginning-of-defun-regex
+  (concat julia-function-regex "\\|"
+          julia-function-assignment-regex "\\|"
+          "\\_<macro\\_>")
+  "Regex matching beginning of Julia function or macro.")
+
+(defun julia-syntax-context-type (&optional syntax-ppss)
+  "Return the context type using SYNTAX-PPSS.
+TYPE can be `comment', `string' or `paren'."
+  (let ((ppss (or syntax-ppss (syntax-ppss))))
+    (cond
+     ((nth 8 ppss) (if (nth 4 ppss) 'comment 'string))
+     ((nth 1 ppss) 'paren))))
+
+(defsubst julia-syntax-comment-or-string-p (&optional syntax-ppss)
+  "Return non-nil if SYNTAX-PPSS is inside string or comment."
+  (nth 8 (or syntax-ppss (syntax-ppss))))
+
+(defun julia-looking-at-beginning-of-defun (&optional syntax-ppss)
+  "Check if point is at `beginning-of-defun' using SYNTAX-PPSS."
+  (and (not (julia-syntax-comment-or-string-p (or syntax-ppss (syntax-ppss))))
+       (save-excursion
+         (beginning-of-line 1)
+         (looking-at julia-beginning-of-defun-regex))))
+
+(defun julia--beginning-of-defun (&optional arg)
+  "Internal implementation of `julia-beginning-of-defun'.
+With positive ARG search backwards, else search forwards."
+  (when (or (null arg) (= arg 0)) (setq arg 1))
+  (let* ((re-search-fn (if (> arg 0)
+                           #'re-search-backward
+                         #'re-search-forward))
+         (line-beg-pos (line-beginning-position))
+         (line-content-start (+ line-beg-pos (current-indentation)))
+         (pos (point-marker))
+         (beg-indentation
+          (and (> arg 0)
+               (save-excursion
+                 (while (and (not (julia-looking-at-beginning-of-defun))
+                             ;; f(x) = ... function bodies may span multiple lines
+                             (or (and (julia-indent-hanging)
+                                      (forward-line -1))
+                                 ;; inside dangling parameter list
+                                 (and (eq 'paren (julia-syntax-context-type))
+                                      (backward-up-list))
+                                 (julia-last-open-block (point-min)))))
+                 (or (and (julia-looking-at-beginning-of-defun)
+                          (+ (current-indentation) julia-indent-offset))
+                     0))))
+         (found
+          (progn
+            (when (and (< arg 0)
+                       (julia-looking-at-beginning-of-defun))
+              (end-of-line 1))
+            (while (and (funcall re-search-fn
+                                 julia-beginning-of-defun-regex nil t)
+                        (or (julia-syntax-comment-or-string-p)
+                            ;; handle nested defuns when moving backwards
+                            ;; by checking matching indentation
+                            (and (> arg 0)
+                                 (not (= (current-indentation) 0))
+                                 (>= (current-indentation) beg-indentation)))))
+            (and (julia-looking-at-beginning-of-defun)
+                 (or (not (= (line-number-at-pos pos)
+                             (line-number-at-pos)))
+                     (and (>= (point) line-beg-pos)
+                          (<= (point) line-content-start)
+                          (> pos line-content-start)))))))
+    (if found
+        (or (beginning-of-line 1) (point))
+      (and (goto-char pos) nil))))
+
+(defun julia-beginning-of-defun (&optional arg)
+  "Move point to `beginning-of-defun'.
+With positive ARG search backwards else search forward.
+ARG nil or 0 defaults to 1.  When searching backwards,
+nested defuns are handled depending on current point position.
+Return non-nil (point) if point moved to `beginning-of-defun'."
+  (when (or (null arg) (= arg 0)) (setq arg 1))
+  (let ((found))
+    (while (and (not (= arg 0))
+                (let ((keep-searching-p
+                       (julia--beginning-of-defun arg)))
+                  (when (and keep-searching-p (null found))
+                    (setq found t))
+                  keep-searching-p))
+      (setq arg (if (> arg 0) (1- arg) (1+ arg))))
+    found))
+
+(defun julia-end-of-defun (&optional arg)
+  "Move point to the end of the current function.
+Return nil if point is not in a function, otherwise point."
+  (interactive)
+  (let ((beg-defun-indent)
+        (beg-pos (point)))
+    (when (or (julia-looking-at-beginning-of-defun)
+              (julia-beginning-of-defun 1)
+              (julia-beginning-of-defun -1))
+      (beginning-of-line)
+      (if (looking-at-p julia-function-assignment-regex)
+          ;; f(x) = ...
+          (progn
+            ;; skip any dangling lines
+            (while (and (forward-line)
+                        (not (eobp))
+                        (or (julia-indent-hanging)
+                            ;; dangling closing paren
+                            (and (eq 'paren (julia-syntax-context-type))
+                                 (search-forward ")"))))))
+        ;; otherwise skip forward to matching indentation (not in string/comment)
+        (setq beg-defun-indent (current-indentation))
+        (while (and (not (eobp))
+                    (forward-line 1)
+                    (or (julia-syntax-comment-or-string-p)
+                        (> (current-indentation) beg-defun-indent)))))
+      (end-of-line)
+      (point))))
+
+;;; IMENU
+(defvar julia-imenu-generic-expression
+  ;; don't use syntax classes, screws egrep
+  '(("Function (_)" "[ \t]*function[ \t]+\\(_[^ \t\n]*\\)" 1)
+    ("Function" "^[ \t]*function[ \t]+\\([^_][^\t\n]*\\)" 1)
+    ("Const" "[ \t]*const \\([^ \t\n]*\\)" 1)
+    ("Type"  "^[ \t]*[a-zA-Z0-9_]*type[a-zA-Z0-9_]* \\([^ \t\n]*\\)" 1)
+    ("Require"      " *\\(\\brequire\\)(\\([^ \t\n)]*\\)" 2)
+    ("Include"      " *\\(\\binclude\\)(\\([^ \t\n)]*\\)" 2)
+    ;; ("Classes" "^.*setClass(\\(.*\\)," 1)
+    ;; ("Coercions" "^.*setAs(\\([^,]+,[^,]*\\)," 1) ; show from and to
+    ;; ("Generics" "^.*setGeneric(\\([^,]*\\)," 1)
+    ;; ("Methods" "^.*set\\(Group\\|Replace\\)?Method(\"\\(.+\\)\"," 2)
+    ;; ;;[ ]*\\(signature=\\)?(\\(.*,?\\)*\\)," 1)
+    ;; ;;
+    ;; ;;("Other" "^\\(.+\\)\\s-*<-[ \t\n]*[^\\(function\\|read\\|.*data\.frame\\)]" 1)
+    ;; ("Package" "^.*\\(library\\|require\\)(\\(.*\\)," 2)
+    ;; ("Data" "^\\(.+\\)\\s-*<-[ \t\n]*\\(read\\|.*data\.frame\\).*(" 1)))
+    ))
+
+;;;###autoload
+(define-derived-mode julia-mode julia-mode-prog-mode "Julia"
+  "Major mode for editing julia code."
+  (set-syntax-table julia-mode-syntax-table)
+  (set (make-local-variable 'comment-start) "# ")
+  (set (make-local-variable 'comment-start-skip) "#+\\s-*")
+  (set (make-local-variable 'font-lock-defaults) '(julia-font-lock-keywords))
+  (if (< emacs-major-version 24)
+      ;; Emacs 23 doesn't have syntax-propertize-function
+      (set (make-local-variable 'font-lock-syntactic-keywords)
+           (list
+            `(,julia-char-regex
+              (1 "\"") ; Treat ' as a string delimiter.
+              (2 ".")  ; Don't highlight anything between the open and close '.
+              (3 "\""))              ; Treat the close ' as a string delimiter.
+            `(,julia-triple-quoted-string-regex
+              (1 "\"")        ; Treat the first " in """ as a string delimiter.
+              (2 ".")         ; Don't highlight anything between.
+              (3 "\""))))     ; Treat the last " in """ as a string delimiter.
+    ;; Emacs 24 and later has syntax-propertize-function, so use that instead.
+    (set (make-local-variable 'syntax-propertize-function)
+         julia-syntax-propertize-function))
+  (set (make-local-variable 'indent-line-function) 'julia-indent-line)
+  (set (make-local-variable 'beginning-of-defun-function) #'julia-beginning-of-defun)
+  (set (make-local-variable 'end-of-defun-function) #'julia-end-of-defun)
+  (setq indent-tabs-mode nil)
+  (setq imenu-generic-expression julia-imenu-generic-expression)
+  (imenu-add-to-menubar "Imenu"))
+
+(defun julia-manual-deindent ()
+  "Deindent by `julia-indent-offset' regardless of current
+indentation context. To be used to manually indent inside
+strings."
+  (interactive)
+  (indent-line-to (max 0 (- (current-indentation) julia-indent-offset))))
+(define-key julia-mode-map (kbd "<backtab>") 'julia-manual-deindent)
+
+(defvar julia-latexsubs (make-hash-table :test 'equal))
+
+(defun julia-latexsub ()
+  "Perform a LaTeX-like Unicode symbol substitution."
+  (interactive "*i")
+  (let ((orig-pt (point)))
+    (while (not (or (bobp) (= ?\\ (char-before))
+                   (= ?\s (char-syntax (char-before)))))
+      (backward-char))
+    (if (and (not (bobp)) (= ?\\ (char-before)))
+        (progn
+          (backward-char)
+          (let ((sub (gethash (buffer-substring (point) orig-pt) julia-latexsubs)))
+            (if sub
+                (progn
+                  (delete-region (point) orig-pt)
+                  (insert sub))
+              (goto-char orig-pt))))
+      (goto-char orig-pt))))
+
+(defalias 'latexsub 'julia-latexsub)
+
+(defun julia-latexsub-or-indent (arg)
+  "Either indent according to mode or perform a LaTeX-like symbol substution"
+  (interactive "*i")
+  (if (latexsub)
+      (indent-for-tab-command arg)))
+(define-key julia-mode-map (kbd "TAB") 'julia-latexsub-or-indent)
+
+(defalias 'latexsub-or-indent 'julia-latexsub-or-indent)
+
+;;; populate LaTeX symbols hash table from a generated file.
+;;; (See Julia issue #8947 for why we don't use the Emacs tex input mode.)
+(load (expand-file-name "julia-latexsubs" (file-name-directory load-file-name)))
+
+;; Math insertion in julia. Use it with
+;; (add-hook 'julia-mode-hook 'julia-math-mode)
+;; (add-hook 'inferior-julia-mode-hook 'julia-math-mode)
+
+(when (require 'latex nil t)
+  (declare-function LaTeX-math-abbrev-prefix "latex")
+
+  (defun julia-math-insert (s)
+    "Inserts math symbol given by `s'"
+    (when s
+      (let ((sym (gethash (concat "\\" s) julia-latexsubs)))
+        (when sym
+          (insert sym)))))
+
+  (with-no-warnings
+    (define-minor-mode julia-math-mode
+      "A minor mode with easy access to TeX math commands. The
+command is only entered if it is supported in Julia. The
+following commands are defined:
+
+\\{LaTeX-math-mode-map}"
+      nil nil (list (cons (LaTeX-math-abbrev-prefix) LaTeX-math-keymap))
+      (if julia-math-mode
+          (set (make-local-variable 'LaTeX-math-insert-function)
+               'julia-math-insert)))))
+
+;; Code for `inferior-julia-mode'
+(require 'comint)
+
+(defcustom julia-program "julia"
+  "Path to the program used by `inferior-julia'."
+  :type 'string
+  :group 'julia)
+
+(defcustom julia-arguments '("-i" "--color=yes")
+  "Commandline arguments to pass to `julia-program'."
+  :type '(repeat (string :tag "argument"))
+  :group 'julia)
+
+(defvar julia-prompt-regexp "^\\w*> "
+  "Regexp for matching `inferior-julia' prompt.")
+
+(defvar inferior-julia-mode-map
+  (let ((map (nconc (make-sparse-keymap) comint-mode-map)))
+    ;; example definition
+    (define-key map (kbd "TAB") 'julia-latexsub-or-indent)
+    map)
+  "Basic mode map for `inferior-julia-mode'.")
+
+;;;###autoload
+(defun inferior-julia ()
+    "Run an inferior instance of `julia' inside Emacs."
+    (interactive)
+    (let ((julia-program julia-program)
+          (buffer (get-buffer-create "*Julia*")))
+      (when (not (comint-check-proc "*Julia*"))
+        (apply #'make-comint-in-buffer "Julia" "*Julia*"
+               julia-program nil julia-arguments))
+      (pop-to-buffer-same-window "*Julia*")
+      (inferior-julia-mode)))
+
+(defun inferior-julia--initialize ()
+    "Helper function to initialize `inferior-julia'."
+    (setq comint-use-prompt-regexp t))
+
+(define-derived-mode inferior-julia-mode comint-mode "Julia"
+  "Major mode for `inferior-julia'.
+
+\\<inferior-julia-mode-map>"
+  nil "Julia"
+  (setq comint-prompt-regexp julia-prompt-regexp)
+  (setq comint-prompt-read-only t)
+  (set (make-local-variable 'font-lock-defaults) '(julia-font-lock-keywords t))
+  (set (make-local-variable 'paragraph-start) julia-prompt-regexp)
+  (set (make-local-variable 'indent-line-function) 'julia-indent-line))
+
+(add-hook 'inferior-julia-mode-hook 'inferior-julia--initialize)
+
+;;;###autoload
+(defalias 'run-julia #'inferior-julia
+  "Run an inferior instance of `julia' inside Emacs.")
+
+(provide 'julia-mode)
+
+;; Local Variables:
+;; coding: utf-8
+;; byte-compile-warnings: (not obsolete)
+;; End:
+;;; julia-mode.el ends here
diff --git a/elpa/julia-mode-readme.txt b/elpa/julia-mode-readme.txt
new file mode 100644 (file)
index 0000000..1929621
--- /dev/null
@@ -0,0 +1 @@
+This is the official Emacs mode for editing Julia programs.
diff --git a/elpa/pcre2el-20161120.2103/pcre2el-autoloads.el b/elpa/pcre2el-20161120.2103/pcre2el-autoloads.el
new file mode 100644 (file)
index 0000000..7d0e656
--- /dev/null
@@ -0,0 +1,217 @@
+;;; pcre2el-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
+\f
+;;;### (autoloads nil "pcre2el" "pcre2el.el" (23997 31476 537680
+;;;;;;  409000))
+;;; Generated autoloads from pcre2el.el
+
+(defvar pcre-mode nil "\
+Non-nil if PCRE mode is enabled.
+See the `pcre-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `pcre-mode'.")
+
+(custom-autoload 'pcre-mode "pcre2el" nil)
+
+(autoload 'pcre-mode "pcre2el" "\
+Use emulated PCRE syntax for regexps wherever possible.
+
+Advises the `interactive' specs of `read-regexp' and the
+following other functions so that they read PCRE syntax and
+translate to its Emacs equivalent:
+
+- `align-regexp'
+- `find-tag-regexp'
+- `sort-regexp-fields'
+- `isearch-message-prefix'
+- `ibuffer-do-replace-regexp'
+
+Also alters the behavior of `isearch-mode' when searching by regexp.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'pcre-query-replace-regexp "pcre2el" "\
+Perform `query-replace-regexp' using PCRE syntax.
+
+Consider using `pcre-mode' instead of this function.
+
+\(fn)" t nil)
+
+(autoload 'rxt-elisp-to-pcre "pcre2el" "\
+Translate REGEXP, a regexp in Emacs Lisp syntax, to Perl-compatible syntax.
+
+Interactively, reads the regexp in one of three ways. With a
+prefix arg, reads from minibuffer without string escaping, like
+`query-replace-regexp'. Without a prefix arg, uses the text of
+the region if it is active. Otherwise, uses the result of
+evaluating the sexp before point (which might be a string regexp
+literal or an expression that produces a string).
+
+Displays the translated PCRE regexp in the echo area and copies
+it to the kill ring.
+
+Emacs regexp features such as syntax classes which cannot be
+translated to PCRE will cause an error.
+
+\(fn REGEXP)" t nil)
+
+(autoload 'rxt-elisp-to-rx "pcre2el" "\
+Translate REGEXP, a regexp in Emacs Lisp syntax, to `rx' syntax.
+
+See `rxt-elisp-to-pcre' for a description of the interactive
+behavior and `rx' for documentation of the S-expression based
+regexp syntax.
+
+\(fn REGEXP)" t nil)
+
+(autoload 'rxt-elisp-to-strings "pcre2el" "\
+Return a list of all strings matched by REGEXP, an Emacs Lisp regexp.
+
+See `rxt-elisp-to-pcre' for a description of the interactive behavior.
+
+This is useful primarily for getting back the original list of
+strings from a regexp generated by `regexp-opt', but it will work
+with any regexp without unbounded quantifiers (*, +, {2, } and so
+on).
+
+Throws an error if REGEXP contains any infinite quantifiers.
+
+\(fn REGEXP)" t nil)
+
+(autoload 'rxt-toggle-elisp-rx "pcre2el" "\
+Toggle the regexp near point between Elisp string and rx syntax.
+
+\(fn)" t nil)
+
+(autoload 'rxt-pcre-to-elisp "pcre2el" "\
+Translate PCRE, a regexp in Perl-compatible syntax, to Emacs Lisp.
+
+Interactively, uses the contents of the region if it is active,
+otherwise reads from the minibuffer. Prints the Emacs translation
+in the echo area and copies it to the kill ring.
+
+PCRE regexp features that cannot be translated into Emacs syntax
+will cause an error. See the commentary section of pcre2el.el for
+more details.
+
+\(fn PCRE &optional FLAGS)" t nil)
+
+(defalias 'pcre-to-elisp 'rxt-pcre-to-elisp)
+
+(autoload 'rxt-pcre-to-rx "pcre2el" "\
+Translate PCRE, a regexp in Perl-compatible syntax, to `rx' syntax.
+
+See `rxt-pcre-to-elisp' for a description of the interactive behavior.
+
+\(fn PCRE &optional FLAGS)" t nil)
+
+(autoload 'rxt-pcre-to-strings "pcre2el" "\
+Return a list of all strings matched by PCRE, a Perl-compatible regexp.
+
+See `rxt-elisp-to-pcre' for a description of the interactive
+behavior and `rxt-elisp-to-strings' for why this might be useful.
+
+Throws an error if PCRE contains any infinite quantifiers.
+
+\(fn PCRE &optional FLAGS)" t nil)
+
+(autoload 'rxt-explain-elisp "pcre2el" "\
+Insert the pretty-printed `rx' syntax for REGEXP in a new buffer.
+
+REGEXP is a regular expression in Emacs Lisp syntax. See
+`rxt-elisp-to-pcre' for a description of how REGEXP is read
+interactively.
+
+\(fn REGEXP)" t nil)
+
+(autoload 'rxt-explain-pcre "pcre2el" "\
+Insert the pretty-printed `rx' syntax for REGEXP in a new buffer.
+
+REGEXP is a regular expression in PCRE syntax. See
+`rxt-pcre-to-elisp' for a description of how REGEXP is read
+interactively.
+
+\(fn REGEXP &optional FLAGS)" t nil)
+
+(autoload 'rxt-quote-pcre "pcre2el" "\
+Return a PCRE regexp which matches TEXT literally.
+
+Any PCRE metacharacters in TEXT will be quoted with a backslash.
+
+\(fn TEXT)" nil nil)
+
+(autoload 'rxt-explain "pcre2el" "\
+Pop up a buffer with pretty-printed `rx' syntax for the regex at point.
+
+Chooses regex syntax to read based on current major mode, calling
+`rxt-explain-elisp' if buffer is in `emacs-lisp-mode' or
+`lisp-interaction-mode', or `rxt-explain-pcre' otherwise.
+
+\(fn)" t nil)
+
+(autoload 'rxt-convert-syntax "pcre2el" "\
+Convert regex at point to other kind of syntax, depending on major mode.
+
+For buffers in `emacs-lisp-mode' or `lisp-interaction-mode',
+calls `rxt-elisp-to-pcre' to convert to PCRE syntax. Otherwise,
+calls `rxt-pcre-to-elisp' to convert to Emacs syntax.
+
+The converted syntax is displayed in the echo area and copied to
+the kill ring; see the two functions named above for details.
+
+\(fn)" t nil)
+
+(autoload 'rxt-convert-to-rx "pcre2el" "\
+Convert regex at point to RX syntax. Chooses Emacs or PCRE syntax by major mode.
+
+\(fn)" t nil)
+
+(autoload 'rxt-convert-to-strings "pcre2el" "\
+Convert regex at point to RX syntax. Chooses Emacs or PCRE syntax by major mode.
+
+\(fn)" t nil)
+
+(autoload 'rxt-mode "pcre2el" "\
+Regex translation utilities.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'turn-on-rxt-mode "pcre2el" "\
+Turn on `rxt-mode' in the current buffer.
+
+\(fn)" t nil)
+
+(defvar rxt-global-mode nil "\
+Non-nil if Rxt-Global mode is enabled.
+See the `rxt-global-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `rxt-global-mode'.")
+
+(custom-autoload 'rxt-global-mode "pcre2el" nil)
+
+(autoload 'rxt-global-mode "pcre2el" "\
+Toggle Rxt mode in all buffers.
+With prefix ARG, enable Rxt-Global mode if ARG is positive;
+otherwise, disable it.  If called from Lisp, enable the mode if
+ARG is omitted or nil.
+
+Rxt mode is enabled in all buffers where
+`turn-on-rxt-mode' would do it.
+See `rxt-mode' for more information on Rxt mode.
+
+\(fn &optional ARG)" t nil)
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+;;; pcre2el-autoloads.el ends here
diff --git a/elpa/pcre2el-20161120.2103/pcre2el-pkg.el b/elpa/pcre2el-20161120.2103/pcre2el-pkg.el
new file mode 100644 (file)
index 0000000..e0297eb
--- /dev/null
@@ -0,0 +1,2 @@
+;;; -*- no-byte-compile: t -*-
+(define-package "pcre2el" "20161120.2103" "regexp syntax converter" '((emacs "24") (cl-lib "0.3")) :commit "0b5b2a2c173aab3fd14aac6cf5e90ad3bf58fa7d" :authors '(("joddie <jonxfield at gmail.com>")) :maintainer '("joddie <jonxfield at gmail.com>") :url "https://github.com/joddie/pcre2el")
diff --git a/elpa/pcre2el-20161120.2103/pcre2el.el b/elpa/pcre2el-20161120.2103/pcre2el.el
new file mode 100644 (file)
index 0000000..bea8eff
--- /dev/null
@@ -0,0 +1,3157 @@
+;;; pcre2el.el --- regexp syntax converter -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012-2015 Jon Oddie <jonxfieldNOSPAMgmail.com>
+
+;; Author:                     joddie <jonxfield at gmail.com>
+;; Hacked additionally by:     opensource at hardakers dot net
+;; Created:                    14 Feb 2012
+;; Updated:                    13 December 2015
+;; Version:                     1.8
+;; Package-Version: 20161120.2103
+;; Url:                         https://github.com/joddie/pcre2el
+;; Package-Requires:            ((emacs "24") (cl-lib "0.3"))
+
+;; This file is NOT part of GNU Emacs.
+
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of the
+;; License, or (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see `http://www.gnu.org/licenses/'.
+
+;; This file incorporates work covered by the following copyright and
+;; permission notice:
+;;
+;; Copyright (c) 1993-2002 Richard Kelsey and Jonathan Rees
+;; Copyright (c) 1994-2002 by Olin Shivers and Brian D. Carlstrom.
+;; Copyright (c) 1999-2002 by Martin Gasbichler.
+;; Copyright (c) 2001-2002 by Michael Sperber.
+;; All rights reserved.
+;;
+;; Redistribution and use in source and binary forms, with or without
+;; modification, are permitted provided that the following conditions
+;; are met: 1. Redistributions of source code must retain the above
+;; copyright notice, this list of conditions and the following
+;; disclaimer. 2. Redistributions in binary form must reproduce the
+;; above copyright notice, this list of conditions and the following
+;; disclaimer in the documentation and/or other materials provided
+;; with the distribution. 3. The name of the authors may not be used
+;; to endorse or promote products derived from this software without
+;; specific prior written permission.
+;;
+;; THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR
+;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+;;; Commentary:
+
+;; 1 Overview
+;; ==========
+
+;;   `pcre2el' or `rxt' (RegeXp Translator or RegeXp Tools) is a utility
+;;   for working with regular expressions in Emacs, based on a
+;;   recursive-descent parser for regexp syntax. In addition to converting
+;;   (a subset of) PCRE syntax into its Emacs equivalent, it can do the
+;;   following:
+
+;;   - convert Emacs syntax to PCRE
+;;   - convert either syntax to `rx', an S-expression based regexp syntax
+;;   - untangle complex regexps by showing the parse tree in `rx' form and
+;;     highlighting the corresponding chunks of code
+;;   - show the complete list of strings (productions) matching a regexp,
+;;     provided the list is finite
+;;   - provide live font-locking of regexp syntax (so far only for Elisp
+;;     buffers -- other modes on the TODO list)
+
+
+;; 2 Usage
+;; =======
+
+;;   Enable `rxt-mode' or its global equivalent `rxt-global-mode' to get
+;;   the default key-bindings. There are three sets of commands: commands
+;;   that take a PCRE regexp, commands which take an Emacs regexp, and
+;;   commands that try to do the right thing based on the current
+;;   mode. Currently, this means Emacs syntax in `emacs-lisp-mode' and
+;;   `lisp-interaction-mode', and PCRE syntax everywhere else.
+
+;;   The default key bindings all begin with `C-c /' and have a mnemonic
+;;   structure: `C-c / <source> <target>', or just `C-c / <target>' for the
+;;   "do what I mean" commands. The complete list of key bindings is given
+;;   here and explained in more detail below:
+
+;;   - "Do-what-I-mean" commands:
+;;     `C-c / /': `rxt-explain'
+;;     `C-c / c': `rxt-convert-syntax'
+;;     `C-c / x': `rxt-convert-to-rx'
+;;     `C-c / '': `rxt-convert-to-strings'
+
+;;   - Commands that work on a PCRE regexp:
+;;     `C-c / p e': `rxt-pcre-to-elisp'
+;;     `C-c / %': `pcre-query-replace-regexp'
+;;     `C-c / p x': `rxt-pcre-to-rx'
+;;     `C-c / p '': `rxt-pcre-to-strings'
+;;     `C-c / p /': `rxt-explain-pcre'
+
+;;   - Commands that work on an Emacs regexp:
+;;     `C-c / e /': `rxt-explain-elisp'
+;;     `C-c / e p': `rxt-elisp-to-pcre'
+;;     `C-c / e x': `rxt-elisp-to-rx'
+;;     `C-c / e '': `rxt-elisp-to-strings'
+;;     `C-c / e t': `rxt-toggle-elisp-rx'
+;;     `C-c / t': `rxt-toggle-elisp-rx'
+
+
+;; 2.1 Interactive input and output
+;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+;;   When used interactively, the conversion commands can read a regexp
+;;   either from the current buffer or from the minibuffer. The output is
+;;   displayed in the minibuffer and copied to the kill-ring.
+
+;;   - When called with a prefix argument (`C-u'), they read a regular
+;;     expression from the minibuffer literally, without further processing
+;;     -- meaning there's no need to double the backslashes if it's an
+;;     Emacs regexp.  This is the same way commands like
+;;     `query-replace-regexp' read input.
+
+;;   - When the region is active, they use they the region contents, again
+;;     literally (without any translation of string syntax).
+
+;;   - With neither a prefix arg nor an active region, the behavior depends
+;;     on whether the command expects an Emacs regexp or a PCRE one.
+
+;;     Commands that take an Emacs regexp behave like `C-x C-e': they
+;;     evaluate the sexp before point (which could be simply a string
+;;     literal) and use its value. This is designed for use in Elisp
+;;     buffers. As a special case, if point is *inside* a string, it's
+;;     first moved to the string end, so in practice they should work as
+;;     long as point is somewhere within the regexp literal.
+
+;;     Commands that take a PCRE regexp try to read a Perl-style delimited
+;;     regex literal *after* point in the current buffer, including its
+;;     flags. For example, putting point before the `m' in the following
+;;     example and doing `C-c / p e' (`rxt-pcre-to-elisp') displays
+;;     `\(?:bar\|foo\)', correctly stripping out the whitespace and
+;;     comment:
+
+;;     ,----
+;;     | $x =~ m/  foo   |  (?# comment) bar /x
+;;     `----
+
+;;     The PCRE reader currently only works with `/ ... /' delimiters. It
+;;     will ignore any preceding `m', `s', or `qr' operator, as well as the
+;;     replacement part of an `s' construction.
+
+;;     Readers for other PCRE-using languages are on the TODO list.
+
+;;   The translation functions display their result in the minibuffer and
+;;   copy it to the kill ring. When translating something into Elisp
+;;   syntax, you might need to use the result either literally (e.g. for
+;;   interactive input to a command like `query-replace-regexp'), or as a
+;;   string to paste into Lisp code.  To allow both uses,
+;;   `rxt-pcre-to-elisp' copies both versions successively to the
+;;   kill-ring. The literal regexp without string quoting is the top
+;;   element of the kill-ring, while the Lisp string is the
+;;   second-from-top. You can paste the literal regexp somewhere by doing
+;;   `C-y', or the Lisp string by `C-y M-y'.
+
+
+;; 2.2 Syntax conversion commands
+;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+;;   `rxt-convert-syntax' (`C-c / c') converts between Emacs and PCRE
+;;   syntax, depending on the major mode in effect when called.
+;;   Alternatively, you can specify the conversion direction explicitly by
+;;   using either `rxt-pcre-to-elisp' (`C-c / p e') or `rxt-elisp-to-pcre'
+;;   (`C-c / e p').
+
+;;   Similarly, `rxt-convert-to-rx' (`C-c / x') converts either kind of
+;;   syntax to `rx' form, while `rxt-convert-pcre-to-rx' (`C-c / p x') and
+;;   `rxt-convert-elisp-to-rx' (`C-c / e x') convert to `rx' from a
+;;   specified source type.
+
+;;   In Elisp buffers, you can use `rxt-toggle-elisp-rx' (`C-c / t' or `C-c
+;;   / e t') to switch the regexp at point back and forth between string
+;;   and `rx' syntax. Point should either be within an `rx' or
+;;   `rx-to-string' form or a string literal for this to work.
+
+
+;; 2.3 PCRE mode (experimental)
+;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+;;   If you want to use emulated PCRE regexp syntax in all Emacs commands,
+;;   try `pcre-mode', which uses Emacs's advice system to make all commands
+;;   that read regexps using the minibuffer use emulated PCRE syntax.  It
+;;   should also work with Isearch.
+
+;;   This feature is still fairly experimental.  It may fail to work or do
+;;   the wrong thing with certain commands.  Please report bugs.
+
+;;   `pcre-query-replace-regexp' was originally defined to do query-replace
+;;   using emulated PCRE regexps, and is now made somewhat obsolete by
+;;   `pcre-mode'.  It is bound to `C-c / %' by default, by analogy with
+;;   `M-%'.  Put the following in your `.emacs' if you want to use
+;;   PCRE-style query replacement everywhere:
+
+;;   ,----
+;;   | (global-set-key [(meta %)] 'pcre-query-replace-regexp)
+;;   `----
+
+;; 2.5 Explain regexps
+;; ~~~~~~~~~~~~~~~~~~~
+
+;;   When syntax-highlighting isn't enough to untangle some gnarly regexp
+;;   you find in the wild, try the 'explain' commands: `rxt-explain' (`C-c
+;;   / /'), `rxt-explain-pcre' (`C-c / p') and `rxt-explain-elisp' (`C-c /
+;;   e'). These display the original regexp along with its pretty-printed
+;;   `rx' equivalent in a new buffer.  Moving point around either in the
+;;   original regexp or the `rx' translation highlights corresponding
+;;   pieces of syntax, which can aid in seeing things like the scope of
+;;   quantifiers.
+
+;;   I call them "explain" commands because the `rx' form is close to a
+;;   plain syntax tree, and this plus the wordiness of the operators
+;;   usually helps to clarify what is going on.  People who dislike Lisp
+;;   syntax might disagree with this assessment.
+
+
+;; 2.6 Generate all matching strings (productions)
+;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+;;   Occasionally you come across a regexp which is designed to match a
+;;   finite set of strings, e.g. a set of keywords, and it would be useful
+;;   to recover the original set. (In Emacs you can generate such regexps
+;;   using `regexp-opt'). The commands `rxt-convert-to-strings' (`C-c /
+;;   ′'), `rxt-pcre-to-strings' (`C-c / p ′') or `rxt-elisp-to-strings'
+;;   (`C-c / e ′') accomplish this by generating all the matching strings
+;;   ("productions") of a regexp.  (The productions are copied to the kill
+;;   ring as a Lisp list).
+
+;;   An example in Lisp code:
+
+;;   ,----
+;;   | (regexp-opt '("cat" "caterpillar" "catatonic"))
+;;   |    ;; => "\\(?:cat\\(?:atonic\\|erpillar\\)?\\)"
+;;   | (rxt-elisp-to-strings "\\(?:cat\\(?:atonic\\|erpillar\\)?\\)")
+;;   |     ;; => '("cat" "caterpillar" "catatonic")
+;;   `----
+
+;;   For obvious reasons, these commands only work with regexps that don't
+;;   include any unbounded quantifiers like `+' or `*'. They also can't
+;;   enumerate all the characters that match a named character class like
+;;   `[[:alnum:]]'. In either case they will give a (hopefully meaningful)
+;;   error message. Due to the nature of permutations, it's still possible
+;;   for a finite regexp to generate a huge number of productions, which
+;;   will eat memory and slow down your Emacs. Be ready with `C-g' if
+;;   necessary.
+
+
+;; 2.7 RE-Builder support
+;; ~~~~~~~~~~~~~~~~~~~~~~
+
+;;   The Emacs RE-Builder is a useful visual tool which allows using
+;;   several different built-in syntaxes via `reb-change-syntax' (`C-c
+;;   TAB'). It supports Elisp read and literal syntax and `rx', but it can
+;;   only convert from the symbolic forms to Elisp, not the other way. This
+;;   package hacks the RE-Builder to also work with emulated PCRE syntax,
+;;   and to convert transparently between Elisp, PCRE and rx syntaxes. PCRE
+;;   mode reads a delimited Perl-like literal of the form `/ ... /', and it
+;;   should correctly support using the `x' and `s' flags.
+
+
+;; 2.8 Use from Lisp
+;; ~~~~~~~~~~~~~~~~~
+
+;;   Example of using the conversion functions:
+;;   ,----
+;;   | (rxt-pcre-to-elisp "(abc|def)\\w+\\d+")
+;;   |    ;; => "\\(\\(?:abc\\|def\\)\\)[_[:alnum:]]+[[:digit:]]+"
+;;   `----
+
+;;   All the conversion functions take a single string argument, the regexp
+;;   to translate:
+
+;;   - `rxt-pcre-to-elisp'
+;;   - `rxt-pcre-to-rx'
+;;   - `rxt-pcre-to-strings'
+;;   - `rxt-elisp-to-pcre'
+;;   - `rxt-elisp-to-rx'
+;;   - `rxt-elisp-to-strings'
+
+
+;; 3 Bugs and Limitations
+;; ======================
+
+;; 3.1 Limitations on PCRE syntax
+;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+;;   PCRE has a complicated syntax and semantics, only some of which can be
+;;   translated into Elisp. The following subset of PCRE should be
+;;   correctly parsed and converted:
+
+;;   - parenthesis grouping `( .. )', including shy matches `(?: ... )'
+;;   - backreferences (various syntaxes), but only up to 9 per expression
+;;   - alternation `|'
+;;   - greedy and non-greedy quantifiers `*', `*?', `+', `+?', `?' and `??'
+;;           (all of which are the same in Elisp as in PCRE)
+;;   - numerical quantifiers `{M,N}'
+;;   - beginning/end of string `\A', `\Z'
+;;   - string quoting `\Q .. \E'
+;;   - word boundaries `\b', `\B' (these are the same in Elisp)
+;;   - single character escapes `\a', `\c', `\e', `\f', `\n', `\r', `\t',
+;;     `\x', and `\octal digits' (but see below about non-ASCII characters)
+;;   - character classes `[...]' including Posix escapes
+;;   - character classes `\d', `\D', `\h', `\H', `\s', `\S', `\v', `\V'
+;;           both within character class brackets and outside
+;;   - word and non-word characters `\w' and `\W' (Emacs has the same
+;;           syntax, but its meaning is different)
+;;   - `s' (single line) and `x' (extended syntax) flags, in regexp
+;;     literals, or set within the expression via `(?xs-xs)' or `(?xs-xs:
+;;     .... )' syntax
+;;   - comments `(?# ... )'
+
+;;   Most of the more esoteric PCRE features can't really be supported by
+;;   simple translation to Elisp regexps. These include the different
+;;   lookaround assertions, conditionals, and the "backtracking control
+;;   verbs" `(* ...)' . OTOH, there are a few other syntaxes which are
+;;   currently unsupported and possibly could be:
+
+;;   - `\L', `\U', `\l', `\u' case modifiers
+;;   - `\g{...}' backreferences
+
+
+;; 3.2 Other limitations
+;; ~~~~~~~~~~~~~~~~~~~~~
+
+;;   - The order of alternatives and characters in char classes sometimes
+;;     gets shifted around, which is annoying.
+;;   - Although the string parser tries to interpret PCRE's octal and
+;;     hexadecimal escapes correctly, there are problems with matching
+;;     8-bit characters that I don't use enough to properly understand,
+;;     e.g.:
+;;     ,----
+;;     | (string-match-p (rxt-pcre-to-elisp "\\377") "\377") => nil
+;;     `----
+;;     A fix for this would be welcome.
+
+;;   - Most of PCRE's rules for how `^', `\A', `$' and `\Z' interact with
+;;     newlines are not implemented, since they seem less relevant to
+;;     Emacs's buffer-oriented rather than line-oriented model.  However,
+;;     the different meanings of the `.' metacharacter *are* implemented
+;;     (it matches newlines with the `/s' flag, but not otherwise).
+
+;;   - Not currently namespace clean (both `rxt-' and a couple of `pcre-'
+;;     functions).
+
+
+;; 3.3 TODO:
+;; ~~~~~~~~~
+
+;;   - Python-specific extensions to PCRE?
+;;   - Language-specific stuff to enable regexp font-locking and explaining
+;;     in different modes. Each language would need two functions, which
+;;     could be kept in an alist:
+
+;;     1. A function to read PCRE regexps, taking the string syntax into
+;;        account. E.g., Python has single-quoted, double-quoted and raw
+;;        strings, each with different quoting rules.  PHP has the kind of
+;;        belt-and-suspenders solution you would expect: regexps are in
+;;        strings, /and/ you have to include the `/ ...  /' delimiters!
+;;        Duh.
+
+;;     2. A function to copy faces back from the parsed string to the
+;;        original buffer text. This has to recognize any escape sequences
+;;        so they can be treated as a single character.
+
+
+;; 4 Internal details
+;; ==================
+
+;;   `rxt' defines an internal syntax tree representation of regular
+;;   expressions, parsers for Elisp and PCRE syntax, and 'unparsers'
+;;   to convert the internal representation to PCRE or `rx' syntax.
+;;   Converting from the internal representation to Emacs syntax is
+;;   done by converting to `rx' form and passing it to `rx-to-string'.
+;;   See `rxt-parse-re', `rxt-adt->pcre', and `rxt-adt->rx' for
+;;   details.
+
+;;   This code is partially based on Olin Shivers' reference SRE
+;;   implementation in scsh, although it is simplified in some respects and
+;;   extended in others. See `scsh/re.scm', `scsh/spencer.scm' and
+;;   `scsh/posixstr.scm' in the `scsh' source tree for details. In
+;;   particular, `pcre2el' steals the idea of an abstract data type for
+;;   regular expressions and the general structure of the string regexp
+;;   parser and unparser. The data types for character sets are extended in
+;;   order to support symbolic translation between character set
+;;   expressions without assuming a small (Latin1) character set. The
+;;   string parser is also extended to parse a bigger variety of
+;;   constructions, including POSIX character classes and various Emacs and
+;;   Perl regexp assertions. Otherwise, only the bare minimum of scsh's
+;;   abstract data type is implemented.
+
+
+;; 5 Soapbox
+;; =========
+
+;;   Emacs regexps have their annoyances, but it is worth getting used to
+;;   them. The Emacs assertions for word boundaries, symbol boundaries, and
+;;   syntax classes depending on the syntax of the mode in effect are
+;;   especially useful. (PCRE has `\b' for word-boundary, but AFAIK it
+;;   doesn't have separate assertions for beginning-of-word and
+;;   end-of-word). Other things that might be done with huge regexps in
+;;   other languages can be expressed more understandably in Elisp using
+;;   combinations of `save-excursion' with the various searches (regexp,
+;;   literal, skip-syntax-forward, sexp-movement functions, etc.).
+
+;;   There's not much point in using `rxt-pcre-to-elisp' to use PCRE
+;;   notation in a Lisp program you're going to maintain, since you still
+;;   have to double all the backslashes.  Better to just use the converted
+;;   result (or better yet, the `rx' form).
+
+
+;; 6 History and acknowledgments
+;; =============================
+
+;;   This was originally created out of an answer to a stackoverflow
+;;   question:
+;;   [http://stackoverflow.com/questions/9118183/elisp-mechanism-for-converting-pcre-regexps-to-emacs-regexps]
+
+;;   Thanks to:
+
+;;   - Wes Hardaker (hardaker) for the initial inspiration and subsequent
+;;     hacking
+;;   - priyadarshan for requesting RX support
+;;   - Daniel Colascione (dcolascione) for a patch to support Emacs's
+;;     explicitly-numbered match groups
+;;   - Aaron Meurer (asmeurer) for requesting Isearch support
+;;   - Philippe Vaucher (silex) for a patch to support `ibuffer-do-replace-regexp'
+;;     in PCRE mode
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'rx)
+(require 're-builder)
+(require 'advice)
+(require 'ring)
+(require 'pcase)
+
+;;; Customization group
+(defgroup rxt nil
+  "Regex syntax converter and utilities."
+  :version 1.2
+  :group 'tools
+  :group 'lisp
+  :link '(emacs-commentary-link :tag "commentary" "pcre2el.el")
+  :link '(emacs-library-link :tag "lisp file" "pcre2el.el")
+  :link '(url-link :tag "web page" "https://github.com/joddie/pcre2el"))
+
+(defface rxt-highlight-face
+  '((((min-colors 16581375) (background light)) :background "#eee8d5")
+    (((min-colors 16581375) (background dark)) :background "#222222"))
+  "Face for highlighting corresponding regex syntax in `rxt-explain' buffers."
+  :group 'rxt)
+
+(defcustom rxt-verbose-rx-translation nil
+  "Non-nil if `rxt-pcre-to-rx' and `rxt-elisp-to-rx' should use verbose `rx' primitives.
+
+Verbose primitives are things like `line-start' instead of `bol',
+etc."
+  :group 'rxt
+  :type 'boolean)
+
+(defcustom rxt-explain-verbosely t
+  "Non-nil if `rxt-explain-elisp' and `rxt-explain-pcre' should use verbose `rx' primitives.
+
+This overrides the value of `rxt-verbose-rx-translation' for
+these commands only."
+  :group 'rxt
+  :type 'boolean)
+
+\f
+;;;; Macros and functions for writing interactive input and output
+
+;; Macros for handling return values.  If called interactively,
+;; display the value in the echo area and copy it to the kill ring,
+;; otherwise just return the value.  PCREs are copied as unquoted
+;; strings for yanking into Perl, JS, etc.  `rx' forms and other sexps
+;; are copied as `read'-able literals for yanking into Elisp buffers.
+;; Emacs regexps are copied twice: once as an unquoted value for
+;; interactive use, and once as a readable string literal for yanking
+;; into Elisp buffers.
+(defmacro rxt-return-pcre (expr)
+  (let ((value (make-symbol "value")))
+    `(let ((,value ,expr))
+       (when (called-interactively-p 'any)
+         (rxt--kill-pcre ,value))
+       ,value)))
+
+(defmacro rxt-return-sexp (expr)
+  (let ((value (make-symbol "value")))
+    `(let ((,value ,expr))
+       (when (called-interactively-p 'any)
+         (rxt--kill-sexp ,value))
+       ,value)))
+
+(defmacro rxt-return-emacs-regexp (expr)
+  (let ((value (make-symbol "value")))
+    `(let ((,value ,expr))
+       (when (called-interactively-p 'any)
+         (rxt--kill-emacs-regexp ,value))
+       ,value)))
+
+(defun rxt--kill-sexp (value)
+  (let ((lisp-literal (prin1-to-string value)))
+    (message "%s" lisp-literal)
+    (kill-new lisp-literal)))
+
+(defun rxt--kill-pcre (value)
+  (message "%s" value)
+  (kill-new value))
+
+(defun rxt--kill-emacs-regexp (value)
+  (let ((lisp-literal (prin1-to-string value)))
+    (message "%s" value)
+    (kill-new lisp-literal)
+    (kill-new value)))
+
+;; Read an Elisp regexp interactively.
+;;
+;; Three possibilities:
+;;
+;; 1) With a prefix arg, reads literally from the minibuffer, w/o
+;; using string syntax -- just like query-replace-regexp, etc.
+;;
+;; 2) If the region is active, use the text of the region literally
+;; (again w/o string syntax)
+;;
+;; 3) Otherwise, eval the sexp before point (which might be a string
+;; literal or an expression) and use its value. Falls back to method
+;; (1) if this fails to produce a string value.
+;;
+(cl-defun rxt-interactive/elisp (&optional (prompt "Emacs regexp: "))
+  (list
+   (cond (current-prefix-arg
+          (read-string prompt))
+
+         ((use-region-p)
+          (buffer-substring-no-properties (region-beginning) (region-end)))
+
+         (t
+          (condition-case nil
+              (save-excursion
+                (while (nth 3 (syntax-ppss)) (forward-char))
+                (let ((re (eval (preceding-sexp))))
+                  (if (stringp re) re
+                    (read-string prompt))))
+            (error
+             (read-string prompt)))))))
+
+;; Read a PCRE regexp interactively.
+;;
+;; Three possibilities: As above, except that without prefix arg or
+;; active region, tries to read a delimited regexp literal like /.../,
+;; m/.../, or qr/.../ following point in the current buffer. Falls
+;; back to reading from minibuffer if that fails.
+;;
+;; Returns the regexp, with flags as text properties.
+;;
+;; TODO: Different delimiters
+(cl-defun rxt-interactive/pcre (&optional (prompt "PCRE regexp: "))
+  (list
+   (cond (current-prefix-arg
+          (rxt--read-pcre prompt))
+
+         ((use-region-p)
+          (buffer-substring-no-properties (region-beginning) (region-end)))
+
+         (t
+          (condition-case nil
+              (rxt-read-delimited-pcre)
+            (error                     ; Fall back to reading from minibuffer
+             (rxt--read-pcre prompt)))))
+   nil))
+
+(define-minor-mode rxt--read-pcre-mode
+    "Minor-mode with key-bindings for toggling PCRE flags.
+
+You should not normally call this directly.  It will be enabled
+in minibuffers for `read-regexp' and in the `re-builder' buffer
+when `pcre-mode' is active.  These bindings will also be added to
+`isearch-mode-map' in `pcre-mode'."
+  :initial nil
+  :lighter nil
+  :keymap
+  `((,(kbd "C-c s") . ,#'rxt--toggle-s-mode)
+    (,(kbd "C-c x") . ,#'rxt--toggle-x-mode)
+    (,(kbd "C-c i") . ,#'rxt--toggle-i-mode)))
+
+(defun rxt--read-pcre (prompt)
+  "Read a PCRE regexp for translation, together with option flags.
+
+The `s', `x', and `i' flags can be toggled using the following
+commands: \\<rxt--read-pcre-mode-map>
+
+\\[rxt--toggle-s-mode] : toggle `s' (single-line) mode
+\\[rxt--toggle-x-mode] : toggle `x' (extended) mode
+\\[rxt--toggle-i-mode] : toggle `i' (case-insensitive) mode
+
+In single-line mode, `.' will also match newlines.
+In extended mode, whitespace is ignored.
+
+Case-insensitive mode emulates matching without case,
+independently of Emacs's builtin `case-fold-search' setting.
+Note that this does not apply to backreferences."
+  (minibuffer-with-setup-hook #'rxt--read-pcre-mode
+    (read-from-minibuffer prompt)))
+
+(defun rxt--toggle-s-mode ()
+  "Toggle emulated PCRE single-line (s) flag."
+  (interactive)
+  (rxt--toggle-flag ?s))
+
+(defun rxt--toggle-x-mode ()
+  "Toggle emulated PCRE extended (x) flag."
+  (interactive)
+  (rxt--toggle-flag ?x))
+
+(defun rxt--toggle-i-mode ()
+  "Toggle emulated PCRE case-insensitive (i) flag."
+  (interactive)
+  (rxt--toggle-flag ?i))
+
+(defun rxt--toggle-flag (char)
+  "Toggle CHAR, a PCRE flag."
+  (cond
+    ((derived-mode-p 'reb-mode)         ; RE-Builder
+     (rxt--toggle-flag-re-builder char))
+    ((minibufferp)
+     (rxt--toggle-flag-minibuffer char))
+    (isearch-mode
+     (rxt--toggle-flag-isearch char))
+    (t
+     (error "Not in minibuffer, RE-Builder or isearch mode."))))
+
+(defun rxt--toggle-flag-re-builder (char)
+  (save-excursion
+    (goto-char (point-max))
+    (search-backward "/")
+    (forward-char)
+    (when (looking-at (rx (* (any ?i ?s ?x))))
+      (let ((inhibit-modification-hooks t))
+        (replace-match (rxt--xor-flags (match-string 0) char) t t))))
+  (reb-do-update))
+
+(defun rxt--toggle-flag-minibuffer (char)
+  (setf (buffer-substring (minibuffer-prompt-end) (point-max))
+        (rxt--toggle-flag-string (minibuffer-contents) char))
+  (when
+      (and (= (point) (minibuffer-prompt-end))
+           (looking-at (rx "(?" (group (+ (any ?i ?s ?x))) ")")))
+    (forward-sexp)))
+
+(defun rxt--toggle-flag-isearch (char)
+  (when isearch-regexp
+    (setq isearch-string
+          (rxt--toggle-flag-string isearch-string char))
+    (setq isearch-message
+          (mapconcat #'isearch-text-char-description isearch-string ""))
+    (isearch-search-and-update)))
+
+(defun rxt--toggle-flag-string (string char)
+  (if (string-match (rx string-start "(?" (group (+ (any ?i ?s ?x))) ")")
+                    string)
+      (let ((flags (rxt--xor-flags (match-string 1 string) char)))
+        (if (string= flags "")
+            (replace-match "" t t string)
+          (replace-match flags t t string 1)))
+    (format "(?%c)%s" char string)))
+
+(defun rxt--xor-flags (flags char)
+  (concat
+   (sort
+    (cl-set-exclusive-or (string-to-list flags) (list char))
+    #'<)))
+
+\f
+;;;; Minor mode for using emulated PCRE syntax
+
+(defvar pcre-old-isearch-search-fun-function nil
+  "Original value of `isearch-search-fun-function' before entering `pcre-mode.'
+
+This function is wrapped by `pcre-isearch-search-fun-function'
+and restored on exit from `pcre-mode'.")
+(make-variable-buffer-local 'pcre-old-isearch-search-fun-function)
+
+(defvar pcre-old-isearch-key-bindings nil
+  "Alist of key-bindings to restore in `isearch-mode-map' on exiting `pcre-mode'.")
+
+;;;###autoload
+(define-minor-mode pcre-mode
+  "Use emulated PCRE syntax for regexps wherever possible.
+
+Advises the `interactive' specs of `read-regexp' and the
+following other functions so that they read PCRE syntax and
+translate to its Emacs equivalent:
+
+- `align-regexp'
+- `find-tag-regexp'
+- `sort-regexp-fields'
+- `isearch-message-prefix'
+- `ibuffer-do-replace-regexp'
+
+Also alters the behavior of `isearch-mode' when searching by regexp."
+  nil " PCRE"
+  nil
+  :global t
+
+  (if pcre-mode
+      ;; Enabling
+      (progn
+        ;; Enable advice
+        (ad-enable-regexp "pcre-mode")
+        ;; Set up isearch hooks
+        (add-hook 'isearch-mode-hook #'pcre-isearch-mode-hook)
+        (add-hook 'isearch-mode-end-hook #'pcre-isearch-mode-end-hook)
+        ;; Add the keybindings of `rxt--read-pcre-mode-map' to
+        ;; `isearch-mode-map' (so that they do not cause an exit from
+        ;; `isearch-mode'), and save any existing bindings for those
+        ;; keys to restore on exit from `pcre-mode'.
+        (setq pcre-old-isearch-key-bindings
+              (cl-loop for key being the key-seqs of rxt--read-pcre-mode-map
+                       for def = (lookup-key isearch-mode-map key)
+                       collect (cons (copy-sequence key)
+                                     (if (numberp def) nil def))))
+        (cl-loop for key being the key-seqs of rxt--read-pcre-mode-map
+                 using (key-bindings def)
+                 do (define-key isearch-mode-map key def)))
+
+    ;; Disable advice
+    (ad-disable-regexp "pcre-mode")
+    ;; Remove from isearch hooks
+    (remove-hook 'isearch-mode-hook #'pcre-isearch-mode-hook)
+    (remove-hook 'isearch-mode-end-hook #'pcre-isearch-mode-end-hook)
+    ;; Restore key-bindings
+    (cl-loop for (key . def) in pcre-old-isearch-key-bindings
+             do (define-key isearch-mode-map key def)))
+
+  ;; "Activating" advice re-computes the function definitions, which
+  ;; is necessary whether enabling or disabling
+  (ad-activate-regexp "pcre-mode"))
+
+;;; Cache of PCRE -> Elisp translations
+(defvar pcre-mode-cache-size 100
+  "Number of PCRE-to-Emacs translations to keep in the `pcre-mode' cache.")
+
+(defvar pcre-mode-cache (make-hash-table :test 'equal)
+  "Cache of PCRE-to-Emacs translations used in `pcre-mode'.
+
+Keys are PCRE regexps, values are their Emacs equivalents.")
+
+(defvar pcre-mode-reverse-cache (make-hash-table :test 'equal)
+  "Cache of original PCREs translated to Emacs syntax in `pcre-mode'.
+
+Keys are translated Emacs regexps, values are their original PCRE
+form.  This is used to display the original PCRE regexp in place
+of its translated form.")
+
+(defvar pcre-cache-ring (make-ring pcre-mode-cache-size)
+  "Ring of PCRE-to-Emacs translations used in `pcre-mode'.
+
+When the ring fills up, the oldest element is removed and the
+corresponding entries are deleted from the hash tables
+`pcre-mode-cache' and `pcre-mode-reverse-cache'.")
+
+(defun pcre-to-elisp/cached (pcre)
+  "Translate PCRE to Emacs syntax, caching both forms."
+  (or (gethash pcre pcre-mode-cache)
+      (let ((elisp (rxt-pcre-to-elisp pcre)))
+        (pcre-set-cache pcre elisp)
+        elisp)))
+
+(defun pcre-set-cache (pcre-regexp emacs-regexp)
+  "Add a PCRE-to-Emacs translation to the `pcre-mode' cache."
+  (when (and (not (zerop (length pcre-regexp)))
+             (not (zerop (length emacs-regexp)))
+             (not (gethash pcre-regexp pcre-mode-cache)))
+    (if (= (ring-length pcre-cache-ring) (ring-size pcre-cache-ring))
+        (let* ((old-item (ring-remove pcre-cache-ring))
+               (old-pcre (car old-item))
+               (old-emacs (cdr old-item)))
+          (remhash old-pcre pcre-mode-cache)
+          (remhash old-emacs pcre-mode-reverse-cache))
+      (puthash pcre-regexp emacs-regexp pcre-mode-cache)
+      (puthash emacs-regexp pcre-regexp pcre-mode-reverse-cache)
+      (ring-insert pcre-cache-ring (cons pcre-regexp emacs-regexp)))))
+
+;;; Isearch advice
+(defun pcre-isearch-mode-hook ()
+  (when (not (eq isearch-search-fun-function #'isearch-search-fun-default))
+    (message "Warning: pcre-mode overriding existing isearch function `%s'"
+             isearch-search-fun-function))
+  ;; Prevent an infinite loop, if a previous isearch in pcre-mode
+  ;; exited without restoring the original search function for some
+  ;; reason
+  (unless (eq isearch-search-fun-function #'pcre-isearch-search-fun-function)
+    (setq pcre-old-isearch-search-fun-function isearch-search-fun-function))
+  (set (make-local-variable 'isearch-search-fun-function)
+       #'pcre-isearch-search-fun-function))
+
+(defun pcre-isearch-mode-end-hook ()
+  (setq isearch-search-fun-function pcre-old-isearch-search-fun-function))
+
+(defun pcre-isearch-search-fun-function ()
+  "Enable isearching using emulated PCRE syntax.
+
+This is set as the value of `isearch-search-fun-function' when
+`pcre-mode' is enabled.  Returns a function which searches using
+emulated PCRE regexps when `isearch-regexp' is true."
+  (lambda (string bound noerror)
+    (let ((real-search-function
+           (funcall (or pcre-old-isearch-search-fun-function 'isearch-search-fun-default))))
+      (if (not isearch-regexp)
+          (funcall real-search-function string bound noerror)
+        ;; Raise an error if the regexp ends in an incomplete escape
+        ;; sequence (= odd number of backslashes).
+        ;; TODO: Perhaps this should really be handled in rxt-pcre-to-elisp?
+        (if (isearch-backslash string) (rxt-error "Trailing backslash"))
+        (funcall real-search-function
+                 (pcre-to-elisp/cached string) bound noerror)))))
+
+(defadvice isearch-message-prefix (after pcre-mode disable)
+  "Add \"PCRE\" to the Isearch message when searching by regexp in `pcre-mode'."
+  (when (and isearch-regexp
+             ;; Prevent an inaccurate message if our callback was
+             ;; removed somehow
+             (eq isearch-search-fun-function #'pcre-isearch-search-fun-function))
+    (let ((message ad-return-value))
+      ;; Some hackery to give replacement the same fontification as
+      ;; the original
+      (when
+          (let ((case-fold-search t)) (string-match "regexp" message))
+        (let* ((match (match-string 0 message))
+               (properties (text-properties-at 0 match))
+               (replacement (apply #'propertize "PCRE regexp" properties))
+               (new-message (replace-match replacement t t message)))
+          (setq ad-return-value new-message))))))
+
+(defadvice isearch-fallback
+  (before pcre-mode (want-backslash &optional allow-invalid to-barrier) disable)
+  "Hack to fall back correctly in `pcre-mode'. "
+  ;; A dirty hack to the internals of isearch.  Falling back to a
+  ;; previous match position is necessary when the (Emacs) regexp ends
+  ;; in "*", "?", "\{" or "\|": this is handled in
+  ;; `isearch-process-search-char' by calling `isearch-fallback' with
+  ;; `t' for the value of the first parameter, `want-backslash', in
+  ;; the last two cases.  With PCRE regexps, falling back should take
+  ;; place on "*", "?", "{" or "|", with no backslashes required.
+  ;; This advice handles the last two cases by unconditionally setting
+  ;; `want-backslash' to nil.
+  (ad-set-arg 0 nil))
+
+(defadvice isearch-edit-string
+    (around pcre-mode disable)
+  "Add PCRE mode-toggling keys to Isearch minibuffer in regexp mode."
+  (if isearch-regexp
+      (minibuffer-with-setup-hook
+          #'rxt--read-pcre-mode
+        ad-do-it)
+    ad-do-it))
+
+;;; evil-mode advice
+(defadvice evil-search-function
+    (around pcre-mode (forward regexp-p wrap) disable)
+  (if (and regexp-p (not isearch-mode))
+      (let ((real-search-function ad-do-it))
+        (setq ad-return-value
+              (pcre-decorate-search-function real-search-function)))
+    ad-do-it))
+
+(eval-after-load 'evil
+  '(when pcre-mode
+    (ad-enable-advice 'evil-search-function 'around 'pcre-mode)
+    (ad-activate 'evil-search-function)))
+
+(defun pcre-decorate-search-function (real-search-function)
+  (lambda (string &optional bound noerror count)
+    (funcall real-search-function
+             (pcre-to-elisp/cached string)
+             bound noerror count)))
+
+;;; Other hooks and defadvices
+
+;;;###autoload
+(defun pcre-query-replace-regexp ()
+  "Perform `query-replace-regexp' using PCRE syntax.
+
+Consider using `pcre-mode' instead of this function."
+  (interactive)
+  (let ((old-pcre-mode pcre-mode))
+    (unwind-protect
+        (progn
+          (pcre-mode +1)
+          (call-interactively #'query-replace-regexp))
+      (pcre-mode (if old-pcre-mode 1 0)))))
+
+
+(defadvice add-to-history
+  (before pcre-mode (history-var newelt &optional maxelt keep-all) disable)
+  "Add the original PCRE to query-replace history in `pcre-mode'."
+  (when (eq history-var query-replace-from-history-variable)
+    (let ((original (gethash newelt pcre-mode-reverse-cache)))
+      (when original
+        (ad-set-arg 1 original)))))
+
+(defadvice query-replace-descr
+  (before pcre-mode (from) disable)
+  "Use the original PCRE in Isearch prompts in `pcre-mode'."
+  (let ((original (gethash from pcre-mode-reverse-cache)))
+    (when original
+      (ad-set-arg 0 original))))
+
+;;; The `interactive' specs of the following functions are lifted
+;;; wholesale from the original built-ins, which see.
+(defadvice read-regexp
+  (around pcre-mode first (prompt &optional defaults history) disable)
+  "Read regexp using PCRE syntax and convert to Elisp equivalent."
+  (ad-set-arg 0 (concat "[PCRE] " prompt))
+  (minibuffer-with-setup-hook
+      #'rxt--read-pcre-mode
+    ad-do-it)
+  (setq ad-return-value
+        (pcre-to-elisp/cached ad-return-value)))
+
+(defadvice align-regexp
+  (before pcre-mode first (beg end regexp &optional group spacing repeat) disable)
+  "Read regexp using PCRE syntax and convert to Elisp equivalent."
+  (interactive
+   (append
+    (list (region-beginning) (region-end))
+    (if current-prefix-arg
+        (list (rxt-pcre-to-elisp
+               (read-string "Complex align using PCRE regexp: "
+                            "(\\s*)"))
+              (string-to-number
+               (read-string
+                "Parenthesis group to modify (justify if negative): " "1"))
+              (string-to-number
+               (read-string "Amount of spacing (or column if negative): "
+                            (number-to-string align-default-spacing)))
+              (y-or-n-p "Repeat throughout line? "))
+      (list (concat "\\(\\s-*\\)"
+                    (rxt-pcre-to-elisp
+                     (read-string "Align PCRE regexp: ")))
+            1 align-default-spacing nil)))))
+
+(defadvice ibuffer-do-replace-regexp
+  (before pcre-mode first (from-str to-str) disable)
+  "Read regexp using PCRE syntax and convert to Elisp equivalent."
+  (interactive
+   (let* ((from-str (read-from-minibuffer "[PCRE] Replace regexp: "))
+          (to-str (read-from-minibuffer (concat "[PCRE] Replace " from-str " with: "))))
+     (list (rxt-pcre-to-elisp from-str) to-str))))
+
+(defadvice find-tag-regexp
+  (before pcre-mode first (regexp &optional next-p other-window) disable)
+  "Read regexp using PCRE syntax and convert to Elisp equivalent.
+Perform `find-tag-regexp' using emulated PCRE regexp syntax."
+  (interactive
+   (let ((args (find-tag-interactive "[PCRE] Find tag regexp: " t)))
+     (list (rxt-pcre-to-elisp (nth 0 args))
+           (nth 1 args) (nth 2 args)))))
+
+(defadvice sort-regexp-fields
+  (before pcre-mode first (reverse record-regexp key-regexp beg end) disable)
+  "Read regexp using PCRE syntax and convert to Elisp equivalent."
+  (interactive "P\nsPCRE regexp specifying records to sort: \n\
+sPCRE regexp specifying key within record: \nr")
+  (ad-set-arg 1 (rxt-pcre-to-elisp (ad-get-arg 1)))
+  (ad-set-arg 2 (rxt-pcre-to-elisp (ad-get-arg 2))))
+
+
+\f
+;;; Commands that take Emacs-style regexps as input
+
+;;;###autoload
+(defun rxt-elisp-to-pcre (regexp)
+  "Translate REGEXP, a regexp in Emacs Lisp syntax, to Perl-compatible syntax.
+
+Interactively, reads the regexp in one of three ways. With a
+prefix arg, reads from minibuffer without string escaping, like
+`query-replace-regexp'. Without a prefix arg, uses the text of
+the region if it is active. Otherwise, uses the result of
+evaluating the sexp before point (which might be a string regexp
+literal or an expression that produces a string).
+
+Displays the translated PCRE regexp in the echo area and copies
+it to the kill ring.
+
+Emacs regexp features such as syntax classes which cannot be
+translated to PCRE will cause an error."
+  (interactive (rxt-interactive/elisp))
+  (rxt-return-pcre (rxt-adt->pcre (rxt-parse-elisp regexp))))
+
+;;;###autoload
+(defun rxt-elisp-to-rx (regexp)
+  "Translate REGEXP, a regexp in Emacs Lisp syntax, to `rx' syntax.
+
+See `rxt-elisp-to-pcre' for a description of the interactive
+behavior and `rx' for documentation of the S-expression based
+regexp syntax."
+  (interactive (rxt-interactive/elisp))
+  (rxt-return-sexp (rxt-adt->rx (rxt-parse-elisp regexp))))
+
+;;;###autoload
+(defun rxt-elisp-to-strings (regexp)
+  "Return a list of all strings matched by REGEXP, an Emacs Lisp regexp.
+
+See `rxt-elisp-to-pcre' for a description of the interactive behavior.
+
+This is useful primarily for getting back the original list of
+strings from a regexp generated by `regexp-opt', but it will work
+with any regexp without unbounded quantifiers (*, +, {2, } and so
+on).
+
+Throws an error if REGEXP contains any infinite quantifiers."
+  (interactive (rxt-interactive/elisp))
+  (rxt-return-sexp (rxt-adt->strings (rxt-parse-elisp regexp))))
+
+;;;###autoload
+(defun rxt-toggle-elisp-rx ()
+  "Toggle the regexp near point between Elisp string and rx syntax."
+  (interactive)
+  ;; First, position point before the regex form near point (either
+  ;; a string literal or a list beginning `rx' or `rx-to-string').
+  (let* ((context (syntax-ppss))
+         (string-start (nth 8 context)))
+    (cond (string-start (goto-char string-start))
+          ((looking-back "\"") (backward-sexp))
+          ((looking-at "\"") nil)
+          (t
+           ;; Search backwards, leaving point in place on error
+           (goto-char
+            (save-excursion
+              (skip-syntax-forward "-")
+              (while (not (looking-at
+                           (rx "(" (or "rx" "rx-to-string") symbol-end)))
+                (backward-up-list))
+              (point))))))
+
+  ;; Read and replace the regex following point
+  (let* ((regex (read (current-buffer)))
+         (print-escape-newlines t))
+    (save-excursion
+      (if (listp regex)
+          ;; Replace rx form with string value
+          (prin1 (eval regex) (current-buffer))
+        ;; Pretty-print rx form
+        (save-restriction
+          (let* ((start (point))
+                 (rx-syntax (rxt-elisp-to-rx regex))
+                 (rx-form
+                  (pcase rx-syntax
+                    (`(seq . ,rest) `(rx . ,rest))
+                    (form           `(rx ,form)))))
+            (rxt-print rx-form)
+            (narrow-to-region start (point)))
+          (pp-buffer)
+          ;; remove the extra newline that pp-buffer inserts
+          (goto-char (point-max))
+          (delete-region
+           (point)
+           (save-excursion (skip-chars-backward " \t\n") (point))))))
+    (kill-sexp -1)
+    (indent-pp-sexp)))
+
+
+\f
+;;; Commands that translate PCRE to other formats
+
+;;;###autoload
+(defun rxt-pcre-to-elisp (pcre &optional flags)
+  "Translate PCRE, a regexp in Perl-compatible syntax, to Emacs Lisp.
+
+Interactively, uses the contents of the region if it is active,
+otherwise reads from the minibuffer. Prints the Emacs translation
+in the echo area and copies it to the kill ring.
+
+PCRE regexp features that cannot be translated into Emacs syntax
+will cause an error. See the commentary section of pcre2el.el for
+more details."
+  (interactive (rxt-interactive/pcre))
+  (rxt-return-emacs-regexp
+   (rx-to-string
+    (rxt-pcre-to-rx (rxt--add-flags pcre flags))
+    t)))
+
+;;;###autoload
+(defalias 'pcre-to-elisp 'rxt-pcre-to-elisp)
+
+;;;###autoload
+(defun rxt-pcre-to-rx (pcre &optional flags)
+  "Translate PCRE, a regexp in Perl-compatible syntax, to `rx' syntax.
+
+See `rxt-pcre-to-elisp' for a description of the interactive behavior."
+  (interactive (rxt-interactive/pcre))
+  (rxt-return-sexp (rxt-adt->rx (rxt-parse-pcre (rxt--add-flags pcre flags)))))
+
+;;;###autoload
+(defun rxt-pcre-to-strings (pcre &optional flags)
+  "Return a list of all strings matched by PCRE, a Perl-compatible regexp.
+
+See `rxt-elisp-to-pcre' for a description of the interactive
+behavior and `rxt-elisp-to-strings' for why this might be useful.
+
+Throws an error if PCRE contains any infinite quantifiers."
+  (interactive (rxt-interactive/pcre))
+  (rxt-return-sexp (rxt-adt->strings (rxt-parse-pcre (rxt--add-flags pcre flags)))))
+
+(defun rxt--add-flags (pcre flags)
+  "Prepend FLAGS to PCRE."
+  (if (not (zerop (length flags)))
+      (concat "(?" flags ")" pcre)
+    pcre))
+
+\f
+;;; Regexp explaining functions to display pretty-printed rx syntax
+
+;; When the `rxt-explain' flag is non-nil, `rxt-adt->rx' records
+;; location information for each element of the generated `rx' form,
+;; allowing highlighting corresponding pieces of syntax at point.
+(defvar rxt-explain nil)
+
+(defvar rxt-highlight-overlays nil
+  "List of active location-highlighting overlays in rxt-help-mode buffer.")
+
+;;;###autoload
+(defun rxt-explain-elisp (regexp)
+  "Insert the pretty-printed `rx' syntax for REGEXP in a new buffer.
+
+REGEXP is a regular expression in Emacs Lisp syntax. See
+`rxt-elisp-to-pcre' for a description of how REGEXP is read
+interactively."
+  (interactive (rxt-interactive/elisp))
+  (let ((rxt-explain t)
+        (rxt-verbose-rx-translation rxt-explain-verbosely))
+    (rxt-pp-rx regexp (rxt-elisp-to-rx regexp))))
+
+;;;###autoload
+(defun rxt-explain-pcre (regexp &optional flags)
+  "Insert the pretty-printed `rx' syntax for REGEXP in a new buffer.
+
+REGEXP is a regular expression in PCRE syntax. See
+`rxt-pcre-to-elisp' for a description of how REGEXP is read
+interactively."
+  (interactive (rxt-interactive/pcre))
+  (let ((rxt-explain t)
+        (rxt-verbose-rx-translation rxt-explain-verbosely))
+    (rxt-pp-rx regexp (rxt-pcre-to-rx regexp flags))))
+
+;;;###autoload
+(defun rxt-quote-pcre (text)
+  "Return a PCRE regexp which matches TEXT literally.
+
+Any PCRE metacharacters in TEXT will be quoted with a backslash."
+  (rxt-adt->pcre (rxt-string text)))
+
+\f
+;;;; Commands that depend on the major mode in effect
+
+;; Macro: interactively call one of two functions depending on the
+;; major mode
+(defmacro rxt-mode-dispatch (elisp-function pcre-function)
+  `(if (memq major-mode '(emacs-lisp-mode lisp-interaction-mode))
+       (call-interactively #',elisp-function)
+     (call-interactively #',pcre-function)))
+
+;;;###autoload
+(defun rxt-explain ()
+  "Pop up a buffer with pretty-printed `rx' syntax for the regex at point.
+
+Chooses regex syntax to read based on current major mode, calling
+`rxt-explain-elisp' if buffer is in `emacs-lisp-mode' or
+`lisp-interaction-mode', or `rxt-explain-pcre' otherwise."
+  (interactive)
+  (rxt-mode-dispatch rxt-explain-elisp rxt-explain-pcre))
+
+;;;###autoload
+(defun rxt-convert-syntax ()
+  "Convert regex at point to other kind of syntax, depending on major mode.
+
+For buffers in `emacs-lisp-mode' or `lisp-interaction-mode',
+calls `rxt-elisp-to-pcre' to convert to PCRE syntax. Otherwise,
+calls `rxt-pcre-to-elisp' to convert to Emacs syntax.
+
+The converted syntax is displayed in the echo area and copied to
+the kill ring; see the two functions named above for details."
+  (interactive)
+  (rxt-mode-dispatch rxt-elisp-to-pcre rxt-pcre-to-elisp))
+
+;;;###autoload
+(defun rxt-convert-to-rx ()
+  "Convert regex at point to RX syntax. Chooses Emacs or PCRE syntax by major mode."
+  (interactive)
+  (rxt-mode-dispatch rxt-elisp-to-rx rxt-pcre-to-rx))
+
+;;;###autoload
+(defun rxt-convert-to-strings ()
+  "Convert regex at point to RX syntax. Chooses Emacs or PCRE syntax by major mode."
+  (interactive)
+  (rxt-mode-dispatch rxt-elisp-to-strings rxt-pcre-to-strings))
+
+
+\f
+;;; Minor mode and keybindings
+
+(defvar rxt-mode-map
+  (let ((map (make-sparse-keymap)))
+    ;; Generic
+    (define-key map (kbd "C-c / /") 'rxt-explain)
+    (define-key map (kbd "C-c / c") 'rxt-convert-syntax)
+    (define-key map (kbd "C-c / x") 'rxt-convert-to-rx)
+    (define-key map (kbd "C-c / '") 'rxt-convert-to-strings)
+
+    ;; From PCRE
+    (define-key map (kbd "C-c / p /") 'rxt-explain-pcre)
+    (define-key map (kbd "C-c / p e") 'rxt-pcre-to-elisp)
+    (define-key map (kbd "C-c / p x") 'rxt-pcre-to-rx)
+    (define-key map (kbd "C-c / p '") 'rxt-pcre-to-strings)
+
+    ;; From Elisp
+    (define-key map (kbd "C-c / e /") 'rxt-explain-elisp)
+    (define-key map (kbd "C-c / e p") 'rxt-elisp-to-pcre)
+    (define-key map (kbd "C-c / e x") 'rxt-elisp-to-rx)
+    (define-key map (kbd "C-c / e '") 'rxt-elisp-to-strings)
+    (define-key map (kbd "C-c / e t") 'rxt-toggle-elisp-rx)
+    (define-key map (kbd "C-c / t") 'rxt-toggle-elisp-rx)
+    
+    ;; Search
+    (define-key map (kbd "C-c / %") 'pcre-query-replace-regexp)
+
+    map)
+  "Keymap for `rxt-mode'.")
+
+;;;###autoload
+(define-minor-mode rxt-mode
+  "Regex translation utilities." nil nil)
+
+;;;###autoload
+(defun turn-on-rxt-mode ()
+  "Turn on `rxt-mode' in the current buffer."
+  (interactive)
+  (rxt-mode 1))
+
+;;;###autoload
+(define-globalized-minor-mode rxt-global-mode rxt-mode
+  turn-on-rxt-mode)
+
+\f
+;;;; Syntax explanations
+
+;; Major mode for displaying pretty-printed S-exp syntax
+(define-derived-mode rxt-help-mode emacs-lisp-mode "Regexp Explain"
+  (setq buffer-read-only t)
+  (add-hook 'post-command-hook 'rxt-highlight-text nil t)
+  (rxt-highlight-text))
+
+;; Hack: stop paredit-mode interfering with `rxt-print'
+(eval-when-compile (declare-function paredit-mode "paredit.el"))
+(add-hook 'rxt-help-mode-hook
+          (lambda ()
+            (if (and (boundp 'paredit-mode)
+                     paredit-mode)
+                (paredit-mode 0))))
+
+(define-key rxt-help-mode-map "q" 'quit-window)
+(define-key rxt-help-mode-map "z" 'kill-this-buffer)
+(define-key rxt-help-mode-map "n" 'next-line)
+(define-key rxt-help-mode-map "p" 'previous-line)
+(define-key rxt-help-mode-map "f" 'forward-list)
+(define-key rxt-help-mode-map "b" 'backward-list)
+(define-key rxt-help-mode-map "u" 'backward-up-list)
+(define-key rxt-help-mode-map "d" 'down-list)
+
+(defvar rxt--print-with-overlays nil)
+(defvar rxt--print-depth 0)
+
+(defconst rxt--print-char-alist
+  '((?\a . "\\a")
+    (?\b . "\\b")
+    (?\t . "\\t")
+    (?\n . "\\n")
+    (?\v . "\\v")
+    (?\f . "\\f")
+    (?\r . "\\r")
+    (?\e . "\\e")
+    (?\s . "\\s")
+    (?\\ . "\\\\")
+    (?\d . "\\d"))
+  "Alist of characters to print using an escape sequence in Elisp source.
+See (info \"(elisp) Basic Char Syntax\").")
+
+(defconst rxt--whitespace-display-regexp
+  (rx-to-string `(any ,@(mapcar #'car rxt--print-char-alist))))
+
+(defconst rxt--print-special-chars
+  '(?\( ?\) ?\\ ?\| ?\; ?\' ?\` ?\" ?\# ?\. ?\,)
+  "Characters which require a preceding backslash in Elisp source.
+See (info \"(elisp) Basic Char Syntax\").")
+
+(defun rxt-pp-rx (regexp rx)
+  "Display string regexp REGEXP with its `rx' form RX in an `rxt-help-mode' buffer."
+  (with-current-buffer (get-buffer-create "* Regexp Explain *")
+    (let ((print-escape-newlines t)
+          (inhibit-read-only t))
+      (erase-buffer)
+      (rxt-help-mode)
+      (insert (rxt--propertize-whitespace regexp))
+      (newline 2)
+      (save-excursion
+        (let ((sexp-begin (point))
+              (rxt--print-with-overlays t))
+          (rxt-print rx)
+          (narrow-to-region sexp-begin (point))
+          (pp-buffer)
+          (widen)))
+      (rxt-highlight-text))
+    (pop-to-buffer (current-buffer))))
+
+(cl-defun rxt-print (rx)
+  "Insert RX, an `rx' form, into the current buffer, optionally adding overlays.
+
+Similar to `print' or `prin1', but ensures that `rx' forms are
+printed readably, using character or integer syntax depending on
+context.
+
+If `rxt--print-with-overlays' is non-nil, also creates overlays linking
+elements of RX to their corresponding locations in the source
+string (see `rxt-explain-elisp', `rxt-explain-pcre' and
+`rxt--make-help-overlays')."
+  (let ((start (point)))
+    (cl-typecase rx
+      (cons
+       (pcase rx
+         (`(,(and (or `repeat `**) head)
+             ,(and (pred integerp) from)
+             ,(and (pred integerp) to)
+             . ,rest)
+           (insert (format "(%s %d %d" head from to))
+           (rxt--print-list-tail rest))
+         (`(,(and (or `repeat `= `>=) head)
+             ,(and (pred integerp) n)
+             . ,rest)
+           (insert (format "(%s %d" head n))
+           (rxt--print-list-tail rest))
+         (_
+          (rxt--print-list-tail rx t))))
+      (symbol
+       (cl-case rx
+         ;; `print' escapes the ? characters in the rx operators *?
+         ;; and +?, but this looks bad and is not strictly necessary:
+         ;; (eq (read "*?") (read "*\\?"))     => t
+         ;; (eq (read "+?") (read "+\\?"))     => t
+         ((*? +?) (insert (symbol-name rx)))
+         (t (prin1 rx (current-buffer)))))
+      (string
+       (insert (rxt--propertize-whitespace (prin1-to-string rx))))
+      (character
+       (cond
+         ((eq ?  rx)
+          (insert "?"))
+         ((memq rx rxt--print-special-chars)
+          (insert "?\\" rx))
+         ((assq rx rxt--print-char-alist)
+          (insert "?" (assoc-default rx rxt--print-char-alist)))
+         (t
+          (insert "?" (char-to-string rx)))))
+      (t
+       (prin1 rx (current-buffer))))
+    (when rxt--print-with-overlays
+      (rxt--make-help-overlays rx start (point)))))
+
+(defun rxt--print-list-tail (tail &optional open-paren)
+  (let ((rxt--print-depth (1+ rxt--print-depth)))
+    (let ((done nil))
+      (while (not done)
+        (cl-typecase tail
+          (null
+           (insert ")")
+           (setq done t))
+          (cons
+           (if open-paren
+               (progn
+                 (insert "(")
+                 (setq open-paren nil))
+             (insert " "))
+           (rxt-print (car tail))
+           (setq tail (cdr tail)))
+          (t
+           (insert " . ")
+           (rxt-print tail)
+           (insert ")")
+           (setq done t)))))))
+
+(defun rxt--make-help-overlays (rx start end)
+  (let ((location (rxt-location rx)))
+    (when (and location
+               (rxt-location-start location)
+               (rxt-location-end location))
+      (let* ((sexp-begin (copy-marker start t))
+             (sexp-end (copy-marker end))
+             (sexp-bounds (list sexp-begin sexp-end))
+
+             (source-begin (1+ (rxt-location-start location)))
+             (source-end   (1+ (rxt-location-end   location)))
+             (source-bounds (list source-begin source-end))
+
+             (bounds (list source-bounds sexp-bounds))
+
+             (sexp-ol (make-overlay sexp-begin sexp-end (current-buffer) t nil))
+             (source-ol (make-overlay source-begin source-end (current-buffer) t nil)))
+        (dolist (ol (list sexp-ol source-ol))
+          (overlay-put ol 'priority rxt--print-depth)
+          (overlay-put ol 'rxt-bounds bounds))))))
+
+(defun rxt--propertize-whitespace (string)
+  (let ((string (copy-sequence string))
+        (start 0))
+    (while (string-match rxt--whitespace-display-regexp string start)
+      (put-text-property (match-beginning 0) (match-end 0)
+                         'display
+                         (assoc-default (string-to-char (match-string 0 string))
+                                        rxt--print-char-alist)
+                         string)
+      (setq start (match-end 0)))
+    string))
+
+(defun rxt-highlight-text ()
+  "Highlight the regex syntax at point and its corresponding RX/string form."
+  (let ((all-bounds (get-char-property (point) 'rxt-bounds)))
+    (mapc #'delete-overlay rxt-highlight-overlays)
+    (setq rxt-highlight-overlays nil)
+    (dolist (bounds all-bounds)
+      (cl-destructuring-bind (begin end) bounds
+        (let ((overlay (make-overlay begin end)))
+          (push overlay rxt-highlight-overlays)
+          (overlay-put overlay 'face 'rxt-highlight-face))))))
+
+\f
+;;;; Error handling
+
+(if (fboundp 'define-error)
+    (define-error 'rxt-invalid-regexp "Invalid regexp" 'invalid-regexp)
+  (put 'rxt-invalid-regexp
+         'error-conditions
+         '(rxt-invalid-regexp invalid-regexp error))
+  (put 'rxt-invalid-regexp 'error-message "Invalid regexp"))
+
+(defun rxt-error (&rest format-args)
+  (signal 'rxt-invalid-regexp (list (apply #'format format-args))))
+
+\f
+;;;; Regexp syntax tree data type
+
+;; Base class from which other elements of the syntax-tree inherit
+(cl-defstruct rxt-syntax-tree)
+
+;; Struct representing the original source location
+(cl-defstruct rxt-location
+  source                                ; Either a string or a buffer
+  start end                             ; Offsets, 0- or 1-indexed as appropriate
+  )
+
+(defun rxt-location-text (location)
+  (if (not (rxt-location-p location))
+      nil
+    (let ((start  (rxt-location-start  location))
+          (end    (rxt-location-end    location))
+          (source (rxt-location-source location)))
+      (cond
+        ((buffer-live-p source)
+         (with-current-buffer source
+           (buffer-substring-no-properties start end)))
+        ((stringp source)
+         (substring source start end))
+        (t nil)))))
+
+;; Hash table mapping from syntax-tree elements to source locations.
+(defvar rxt-location-map (make-hash-table :weakness 'key))
+
+(defun rxt-location (object)
+  (gethash object rxt-location-map))
+
+(gv-define-setter rxt-location (value object)
+  `(puthash ,object ,value rxt-location-map))
+
+(defun rxt-source-text (object)
+  (rxt-location-text (rxt-location object)))
+
+(defun rxt-to-string (tree)
+  "Return a readable representation of TREE, a regex syntax-tree object."
+  (or (rxt-source-text tree)
+      (let ((print-level 1))
+        (prin1-to-string tree))))
+(defalias 'rxt-syntax-tree-readable 'rxt-to-string)
+
+;; FIXME
+(defvar rxt-pcre-case-fold nil)
+
+;; Literal string
+(cl-defstruct
+    (rxt-string
+      (:constructor rxt-string (chars &optional case-fold))
+      (:include rxt-syntax-tree))
+  chars
+  (case-fold rxt-pcre-case-fold))
+
+(defun rxt-empty-string ()
+  (rxt-string ""))
+
+(defun rxt-trivial-p (re)
+  (and (rxt-string-p re)
+       (equal (rxt-string-chars re) "")))
+
+;;; Other primitives
+(cl-defstruct (rxt-primitive
+               (:constructor rxt-primitive (pcre rx))
+               (:include rxt-syntax-tree))
+  pcre rx)
+
+(defun rxt-bos () (rxt-primitive "\\A" 'bos))
+(defun rxt-eos () (rxt-primitive "\\Z" 'eos))
+
+(defun rxt-bol () (rxt-primitive "^" 'bol))
+(defun rxt-eol () (rxt-primitive "$" 'eol))
+
+;; FIXME
+(defun rxt-anything () (rxt-primitive "." 'anything))
+(defun rxt-nonl () (rxt-primitive "." 'nonl))
+
+(defun rxt-word-boundary () (rxt-primitive "\\b" 'word-boundary))
+(defun rxt-not-word-boundary () (rxt-primitive "\\B" 'not-word-boundary))
+
+(defun rxt-wordchar () (rxt-primitive "\\w" 'wordchar))
+(defun rxt-not-wordchar () (rxt-primitive "\\W" 'not-wordchar))
+
+(defun rxt-symbol-start () (rxt-primitive nil 'symbol-start))
+(defun rxt-symbol-end () (rxt-primitive nil 'symbol-end))
+
+(defun rxt-bow () (rxt-primitive nil 'bow))
+(defun rxt-eow () (rxt-primitive nil 'eow))
+
+;;; Sequence
+(cl-defstruct
+    (rxt-seq
+     (:constructor make-rxt-seq (elts))
+     (:include rxt-syntax-tree))
+  elts)
+
+;; Slightly smart sequence constructor:
+;; - Flattens nested sequences
+;; - Drops trivial "" elements
+;; - Empty sequence => ""
+;; - Singleton sequence is reduced to its one element.
+(defun rxt-seq (&rest res)        ; Flatten nested seqs & drop ""'s.
+  (let ((res (rxt-seq-flatten res)))
+    (if (consp res)
+        (if (consp (cdr res))
+            (make-rxt-seq res) ; General case
+          (car res))           ; Singleton sequence
+      (rxt-empty-string))))      ; Empty seq -- ""
+
+(defun rxt-seq-flatten (res)
+  (if (consp res)
+      (let ((re (car res))
+            (tail (rxt-seq-flatten (cdr res))))
+        (cond ((rxt-seq-p re)           ; Flatten nested seqs
+               (append (rxt-seq-flatten (rxt-seq-elts re)) tail))
+              ((rxt-trivial-p re) tail) ; Drop trivial elts
+              ((and (rxt-string-p re)   ; Flatten strings
+                    (consp tail)
+                    (rxt-string-p (car tail)))
+               (cons
+                (rxt-string-concat re (car tail))
+                (cdr tail)))
+              (t (cons re tail))))
+    '()))
+
+(defun rxt-string-concat (str1 str2)
+  (if (not (eq (rxt-string-case-fold str1)
+               (rxt-string-case-fold str2)))
+      (make-rxt-seq (list str1 str2))
+    (let ((result
+           (rxt-string (concat (rxt-string-chars str1)
+                               (rxt-string-chars str2))
+                       (rxt-string-case-fold str1)))
+          (first (rxt-location str1))
+          (last  (rxt-location str2)))
+      (when (and first last)
+        (setf (rxt-location result)
+              (make-rxt-location :source (rxt-location-source first)
+                                 :start  (rxt-location-start first)
+                                 :end    (rxt-location-end last))))
+      result)))
+
+;;; Choice (alternation/union)
+(cl-defstruct
+    (rxt-choice
+     (:constructor make-rxt-choice (elts))
+     (:include rxt-syntax-tree))
+  elts)
+
+;;; The empty choice represents a regexp that never matches in any context
+(defvar rxt-empty (make-rxt-choice nil))
+(defun rxt-empty-p (re)
+  (or
+   (and (rxt-choice-p re)
+        (null (rxt-choice-elts re)))
+   (rxt-empty-char-set-p re)))
+
+(defun rxt-choice (&rest alternatives)
+  "Construct the alternation (union) of several regexps.
+
+ALTERNATIVES should be a list of `rxt-syntax-tree' objects.
+The return value is an `rxt-choice' object representing a regexp
+which matches any one of ALTERNATIVES, but simplified in the
+following ways:
+
+- If ALTERNATIVES contains only one element, it is returned unchanged.
+
+- All existing `rxt-choice' elements in ALTERNATIVES are replaced
+  by a flat list of their subexpressions: symbolically,
+  a|(b|(c|d)) is replaced by a|b|c|d
+
+- All character sets and single-character strings in ALTERNATIVES
+  are combined together into one or two character sets,
+  respecting case-folding behaviour."
+  (cl-destructuring-bind (other-elements char-set case-fold-char-set)
+      (rxt--simplify-alternatives alternatives)
+    (let ((simplified-alternatives
+           (append (if (not (rxt-empty-p char-set))
+                       (list char-set)
+                     '())
+                   (if (not (rxt-empty-p case-fold-char-set))
+                       (list case-fold-char-set)
+                     '())
+                   other-elements)))
+      (pcase simplified-alternatives
+        (`()
+          rxt-empty)
+        (`(,element)
+          element)
+        (_
+         (make-rxt-choice simplified-alternatives))))))
+
+(defun rxt--simplify-alternatives (alternatives)
+  "Simplify a set of regexp alternatives.
+
+ALTERNATIVES should be a list of `rxt-syntax-tree' objects to be combined
+into an `rxt-choice' structure.  The result is a three-element
+list (OTHER-ELEMENTS CHAR-SET CASE-FOLDED-CHAR-SET):
+
+- CHAR-SET is an `rxt-char-set-union' containing the union of all
+  case-sensitive character sets and single-character strings in
+  RES.
+
+- CASE-FOLDED-CHAR-SET is similar but combines all the
+  case-insensitive character sets and single-character strings.
+
+- OTHER-ELEMENTS is a list of all other elements, with all
+  `rxt-choice' structures replaced by a flat list of their
+  component subexpressions."
+  (if (null alternatives)
+      (list '()
+            (make-rxt-char-set-union :case-fold nil)
+            (make-rxt-char-set-union :case-fold t))
+    (let* ((re (car alternatives)))
+      (cl-destructuring-bind (tail char-set case-fold-char-set)
+          (rxt--simplify-alternatives (cdr alternatives))
+        (cond ((rxt-choice-p re)         ; Flatten nested choices
+               (list
+                (append (rxt-choice-elts re) tail)
+                char-set
+                case-fold-char-set))
+
+              ((rxt-empty-p re)          ; Drop empty re's.
+               (list tail char-set case-fold-char-set))
+
+              ((rxt-char-set-union-p re) ; Fold char sets together
+               (if (rxt-char-set-union-case-fold re)
+                   (list tail
+                         char-set
+                         (rxt-char-set-union case-fold-char-set re))
+                 (list tail
+                       (rxt-char-set-union char-set re)
+                       case-fold-char-set)))
+
+              ((and (rxt-string-p re)    ; Same for 1-char strings
+                    (= 1 (length (rxt-string-chars re))))
+               (if (rxt-string-case-fold re)
+                   (list tail
+                         char-set
+                         (rxt-char-set-union case-fold-char-set re))
+                 (list tail
+                       (rxt-char-set-union char-set re)
+                       case-fold-char-set)))
+
+              (t                         ; Otherwise.
+               (list (cons re tail) char-set case-fold-char-set)))))))
+
+;;; Repetition
+(cl-defstruct (rxt-repeat
+               (:include rxt-syntax-tree))
+  from to body greedy)
+
+(cl-defun rxt-repeat (from to body &optional (greedy t))
+  (if (equal to 0)
+      (rxt-empty-string)
+    (make-rxt-repeat :from from :to to
+                     :body body :greedy greedy)))
+
+;;; Submatch
+(cl-defstruct
+    (rxt-submatch
+     (:constructor rxt-submatch (body))
+     (:include rxt-syntax-tree))
+  body)
+
+;;; Numbered submatch (Emacs only)
+(cl-defstruct
+    (rxt-submatch-numbered
+     (:constructor rxt-submatch-numbered (n body))
+     (:include rxt-syntax-tree))
+  n
+  body)
+
+;;; Backreference
+(cl-defstruct
+    (rxt-backref
+     (:constructor rxt-backref (n))
+     (:include rxt-syntax-tree))
+  n)
+
+;;; Syntax classes (Emacs only)
+(cl-defstruct (rxt-syntax-class
+               (:include rxt-syntax-tree))
+  symbol)
+
+(defun rxt-syntax-class (symbol)
+  (if (assoc symbol rx-syntax)
+      (make-rxt-syntax-class :symbol symbol)
+    (rxt-error "Invalid syntax class symbol `%s'" symbol)))
+
+;;; Character categories (Emacs only)
+(cl-defstruct (rxt-char-category
+               (:include rxt-syntax-tree))
+  symbol)
+
+(defun rxt-char-category (symbol)
+  (if (assoc symbol rx-categories)
+      (make-rxt-char-category :symbol symbol)
+    (rxt-error "Invalid character category symbol `%s'" symbol)))
+
+
+;;; Char sets
+;; <rxt-char-set> ::= <rxt-char-set-union>
+;;                  | <rxt-char-set-negation>
+;;                  | <rxt-char-set-intersection>
+
+(cl-defstruct (rxt-char-set (:include rxt-syntax-tree)))
+
+;; An rxt-char-set-union represents the union of any number of
+;; characters, character ranges, and POSIX character classes: anything
+;; that can be represented in string notation as a class [ ... ]
+;; without the negation operator.
+(cl-defstruct (rxt-char-set-union
+                (:include rxt-char-set))
+  chars    ; list of single characters
+  ranges   ; list of ranges (from . to)
+  classes  ; list of character classes
+  (case-fold rxt-pcre-case-fold))
+
+;; Test for empty character set
+(defun rxt-empty-char-set-p (cset)
+  (and (rxt-char-set-union-p cset)
+       (null (rxt-char-set-union-chars cset))
+       (null (rxt-char-set-union-ranges cset))
+       (null (rxt-char-set-union-classes cset))))
+
+;; Simple union constructor
+(defun rxt-char-set-union (&rest items)
+  "Construct an regexp character set representing the union of ITEMS.
+
+Each element of ITEMS may be either: a character; a
+single-character string; a single-character `rxt-string' object;
+a cons, (FROM . TO) representing a range of characters; a symbol,
+representing a named character class; or an `rxt-char-set-union'
+object.  All `rxt-char-set-union' objects in ITEMS must have the
+same `case-fold' property."
+  (let ((chars '())
+        (ranges '())
+        (classes '())
+        (case-fold 'undetermined))
+    (dolist (item items)
+      (cl-etypecase item
+        (character
+         (push item chars))
+
+        (string
+         (cl-assert (= 1 (length item)))
+         (push (string-to-char item) chars))
+
+        (rxt-string
+         (cl-assert (= 1 (length (rxt-string-chars item))))
+         (push (string-to-char (rxt-string-chars item)) chars))
+
+        (cons                           ; range (from . to)
+         (cl-check-type (car item) character)
+         (cl-check-type (cdr item) character)
+         (push item ranges))
+
+        (symbol                         ; named character class
+         (push item classes))
+
+        (rxt-char-set-union
+         (if (eq case-fold 'undetermined)
+             (setq case-fold (rxt-char-set-union-case-fold item))
+           (unless (eq case-fold (rxt-char-set-union-case-fold item))
+             (error "Cannot construct union of char-sets with unlike case-fold setting: %S" item)))
+         (setq chars (nconc chars (rxt-char-set-union-chars item)))
+         (setq ranges (nconc ranges (rxt-char-set-union-ranges item)))
+         (setq classes (nconc classes (rxt-char-set-union-classes item))))))
+
+    (make-rxt-char-set-union :chars chars :ranges ranges :classes classes
+                             :case-fold (if (eq case-fold 'undetermined)
+                                            rxt-pcre-case-fold
+                                          case-fold))))
+
+(defun rxt--all-char-set-union-chars (char-set)
+  "Return a list of all characters in CHAR-SET."
+  (cl-assert (rxt-char-set-union-p char-set))
+  (append
+   (rxt-char-set-union-chars char-set)
+   (cl-loop for (start . end) in (rxt-char-set-union-ranges char-set)
+            nconc (cl-loop for char from start to end collect char))))
+
+(defun rxt--simplify-char-set (char-set &optional case-fold-p)
+  "Return a minimal char-set to match the same characters as CHAR-SET.
+
+With optional argument CASE-FOLD-P, return a char-set which
+emulates case-folding behaviour by including both uppercase and
+lowercase versions of all characters in CHAR-SET."
+  (cl-assert (rxt-char-set-union-p char-set))
+  (let* ((classes (rxt-char-set-union-classes char-set))
+         (all-chars
+          (if case-fold-p
+              (cl-loop for char in (rxt--all-char-set-union-chars char-set)
+                       nconc (list (upcase char) (downcase char)))
+            (rxt--all-char-set-union-chars char-set)))
+         (all-ranges
+          (rxt--extract-ranges (rxt--remove-redundant-chars all-chars classes))))
+    (let ((singletons nil)
+          (ranges nil))
+      (cl-loop for (start . end) in all-ranges
+               do
+               (cond ((= start end) (push start singletons))
+                     ((= (1+ start) end)
+                      (push start singletons)
+                      (push end singletons))
+                     (t (push (cons start end) ranges))))
+      (make-rxt-char-set-union :chars (nreverse singletons)
+                               :ranges (nreverse ranges)
+                               :classes classes
+                               :case-fold (if case-fold-p
+                                              nil
+                                            (rxt-char-set-union-case-fold char-set))))))
+
+(defun rxt--remove-redundant-chars (chars classes)
+  "Remove all characters which match a character class in CLASSES from CHARS."
+  (if (null classes)
+      chars
+    (string-to-list
+     (replace-regexp-in-string
+      (rx-to-string `(any ,@classes))
+      ""
+      (apply #'string chars)))))
+
+(defun rxt--extract-ranges (chars)
+  "Return a list of all contiguous ranges in CHARS.
+
+CHARS should be a list of characters (integers).  The return
+value is a list of conses (START . END) representing ranges, such
+that the union of all the ranges represents the same of
+characters as CHARS.
+
+Example:
+    (rxt--extract-ranges (list ?a ?b ?c ?q ?x ?y ?z))
+        => ((?a . ?c) (?q . ?q) (?x . ?z))"
+  (let ((array
+         (apply #'vector
+                (cl-remove-duplicates
+                 (sort (copy-sequence chars) #'<)))))
+    (cl-labels
+        ((recur (start end)
+           (if (< end start)
+               nil
+             (let ((min (aref array start))
+                   (max (aref array end)))
+               (if (= (- max min) (- end start))
+                   (list (cons min max))
+                 (let* ((split-point (/ (+ start end) 2))
+                        (left (recur start split-point))
+                        (right (recur (1+ split-point) end)))
+                   (merge left right))))))
+         (merge (left right)
+           (cond ((null left) right)
+                 ((null right) left)
+                 (t
+                  (let ((last-left (car (last left)))
+                        (first-right (car right)))
+                    (if (= (1+ (cdr last-left))
+                           (car first-right))
+                        (append (cl-subseq left 0 -1)
+                                (list
+                                 (cons (car last-left)
+                                       (cdr first-right)))
+                                (cl-subseq right 1))
+                      (append left right)))))))
+      (recur 0 (1- (length array))))))
+
+;;; Set complement of character set, syntax class, or character
+;;; category
+
+;; In general, all character sets that can be represented in string
+;; notation as [^ ... ] (but see `rxt-char-set-intersection', below), plus
+;; Emacs' \Sx and \Cx constructions.
+(cl-defstruct (rxt-char-set-negation
+               (:include rxt-char-set))
+  elt)
+
+(defun rxt-negate (char-set)
+  "Construct the logical complement (negation) of CHAR-SET.
+
+CHAR-SET may be any of the following types: `rxt-char-set-union',
+`rxt-syntax-class', `rxt-char-category', or `rxt-char-set-negation'."
+  (cl-etypecase char-set
+    ((or rxt-char-set-union rxt-syntax-class rxt-char-category)
+     (make-rxt-char-set-negation :elt char-set))
+
+    (rxt-char-set-negation
+     (rxt-char-set-negation-elt char-set))))
+
+;;; Intersections of char sets
+
+;; These are difficult to represent in general, but can be constructed
+;; in Perl using double negation; for example: [^\Wabc] means the set
+;; complement of [abc] with respect to the universe of "word
+;; characters": (& (~ (~ word)) (~ ("abc"))) == (& word (~ ("abc")))
+;; == (- word ("abc"))
+
+(cl-defstruct (rxt-char-set-intersection
+               (:include rxt-char-set))
+  elts)
+
+;; Intersection constructor
+(defun rxt-char-set-intersection (&rest charsets)
+  (let ((elts '())
+        (cmpl (make-rxt-char-set-union)))
+    (dolist (cset (rxt-int-flatten charsets))
+      (cond
+       ((rxt-char-set-negation-p cset)
+        ;; Fold negated charsets together: ~A & ~B = ~(A|B)
+        (setq cmpl (rxt-char-set-union cmpl (rxt-char-set-negation-elt cset))))
+
+       ((rxt-char-set-union-p cset)
+        (push cset elts))
+
+       (t
+        (rxt-error "Can't take intersection of non-character-set %S" cset))))
+
+    (if (null elts)
+        (rxt-negate cmpl)
+      (unless (rxt-empty-char-set-p cmpl)
+        (push (rxt-negate cmpl) elts))
+      (if (null (cdr elts))
+          (car elts)      ; singleton case
+        (make-rxt-char-set-intersection :elts elts)))))
+
+;; Constructor helper: flatten nested intersections
+(defun rxt-int-flatten (csets)
+  (if (consp csets)
+      (let ((cset (car csets))
+            (tail (rxt-int-flatten (cdr csets))))
+        (if (rxt-char-set-intersection-p cset)
+            (append (rxt-int-flatten (rxt-char-set-intersection-elts cset)) tail)
+          (cons cset tail)))
+    '()))
+
+
+\f
+;;;; Macros for building the parser
+
+(defmacro rxt-token-case (&rest cases)
+  "Consume a token at point and evaluate corresponding forms.
+
+CASES is a list of `cond'-like clauses, (REGEXP BODY ...) where
+the REGEXPs define possible tokens which may appear at point. The
+CASES are considered in order. For each case, if the text at
+point matches REGEXP, then point is moved to the end of the
+matched token, the corresponding BODY is evaluated and their
+value returned. The matched token is available within the BODY
+forms as (match-string 0).
+
+There can be a default case where REGEXP is `t', which evaluates
+the corresponding FORMS but does not move point.
+
+Returns `nil' if none of the CASES matches."
+  (declare (debug (&rest (sexp &rest form))))
+  `(cond
+     ,@(cl-loop for (token . action) in cases
+                collect
+                (if (eq token t)
+                    `(t ,@action)
+                  `((looking-at ,token)
+                    (goto-char (match-end 0))
+                    ,@action)))))
+
+(defmacro rxt-with-source-location (&rest body)
+  "Evaluate BODY and record source location information on its value. 
+
+BODY may evaluate to any kind of object, but its value should
+generally not be `eq' to any other object."
+  (declare (debug (&rest form)))
+  (let ((begin (make-symbol "begin"))
+        (value (make-symbol "value")))
+    `(let ((,begin (point))
+           (,value ,(macroexp-progn body)))
+       (setf (rxt-location ,value)
+             (make-rxt-location :source rxt-source-text-string
+                                :start  (1- ,begin)
+                                :end    (1- (point))))
+       ,value)))
+
+;; Read PCRE + flags
+(defun rxt-read-delimited-pcre ()
+  "Read a Perl-style delimited regexp and flags from the current buffer.
+
+Point should be before the regexp literal before calling
+this. Currently only regexps delimited by / ... / are supported.
+A preceding \"m\", \"qr\" or \"s\" will be ignored, as will the
+replacement string in an s/.../.../ construction.
+
+Returns two strings: the regexp and the flags."
+  (save-excursion
+    (skip-syntax-forward "-")
+
+    ;; Skip m, qr, s
+    (let ((is-subst (rxt-token-case
+                     ("s" t)
+                     ((rx (or "m" "qr")) nil))))
+
+      (when (not (looking-at "/"))
+        (error "Only Perl regexps delimited by slashes are supported"))
+      (let ((beg (match-end 0))
+            (delim (rx (not (any "\\"))
+                       (group "/"))))
+        (search-forward-regexp delim)
+        (let ((end (match-beginning 1)))
+          (when is-subst (search-forward-regexp delim))
+          (let ((pcre (buffer-substring-no-properties beg end)))
+            (rxt-token-case
+             ("[gimosx]*"
+              (rxt--add-flags pcre (match-string-no-properties 0))))))))))
+
+\f
+;;;; Elisp and PCRE string notation parser
+
+;;; Parser constants
+(defconst rxt-pcre-char-set-alist
+  `((?w .                               ; "word" characters
+        (?_ alnum))
+    (?d .                               ; digits
+        (digit))
+    (?h .                               ; horizontal whitespace
+        (#x0009 #x0020 #x00A0 #x1680 #x180E #x2000 #x2001 #x2002 #x2003
+                #x2004 #x2005 #x2006 #x2007 #x2008 #x2009 #x200A #x202F
+                #x205F #x3000))
+    (?s .                               ; whitespace
+        (9 10 12 13 32))
+    (?v .                               ; vertical whitespace
+        (#x000A #x000B #x000C #x000D #x0085 #x2028 #x2029))))
+
+(defconst rxt-pcre-named-classes-regexp
+  (rx "[:"
+      (submatch
+       (or "alnum" "alpha" "ascii" "blank" "cntrl" "digit" "graph" "lower"
+           "print" "punct" "space" "upper" "word" "xdigit"))
+      ":]"))
+
+(defconst rxt-elisp-named-classes-regexp
+  (rx "[:"
+      (submatch
+       (or "alnum" "alpha" "ascii" "blank" "cntrl" "digit" "graph" "lower"
+           "print" "punct" "space" "upper" "word" "xdigit"
+           "unibyte" "nonascii" "multibyte"))
+      ":]"))
+
+;;; The following dynamically bound variables control the operation of
+;;; the parser (see `rxt-parse-re'.)
+(defvar rxt-parse-pcre nil
+  "t if the rxt string parser is parsing PCRE syntax, nil for Elisp syntax.
+
+This should only be let-bound internally, never set otherwise.")
+
+(defvar rxt-pcre-extended-mode nil
+  "t if the rxt string parser is emulating PCRE's \"extended\" mode.
+
+In extended mode (indicated by /x in Perl/PCRE), whitespace
+outside of character classes and \\Q...\\E quoting is ignored,
+and a `#' character introduces a comment that extends to the end
+of line.")
+
+(defvar rxt-pcre-s-mode nil
+  "t if the rxt string parser is emulating PCRE's single-line \"/s\" mode.
+
+When /s is used, PCRE's \".\" matches newline characters, which
+otherwise it would not match.")
+
+(defvar rxt-pcre-case-fold nil
+  "non-nil to emulate PCRE's case-insensitive \"/i\" mode in translated regexps.")
+
+(defvar rxt-branch-end-regexp nil)
+(defvar rxt-choice-regexp nil)
+(defvar rxt-brace-begin-regexp nil)
+(defvar rxt-m-to-n-brace-regexp nil)
+(defvar rxt-m-to-?-brace-regexp nil)
+(defvar rxt-m-brace-regexp nil)
+(defvar rxt-named-classes-regexp nil)
+
+(defvar rxt-subgroup-count nil)
+(defvar rxt-source-text-string nil)
+
+(defun rxt-parse-pcre (re)
+  (rxt-parse-re re t))
+
+(defun rxt-parse-elisp (re)
+  (rxt-parse-re re nil))
+
+(defun rxt-parse-re (re pcre-p)
+  (let* ((rxt-parse-pcre pcre-p)
+         (rxt-pcre-extended-mode nil)
+         (rxt-pcre-s-mode        nil)
+         (rxt-pcre-case-fold     nil)
+
+         ;; Bind regexps to match syntax that differs between PCRE and
+         ;; Elisp only in the addition of a backslash "\"
+         (escape (if pcre-p "" "\\"))
+         (rxt-choice-regexp
+          (rx-to-string `(seq ,escape "|")))
+         (rxt-branch-end-regexp
+          (rx-to-string `(or buffer-end
+                             (seq ,escape (or "|" ")")))))
+         (rxt-brace-begin-regexp
+          (rx-to-string `(seq ,escape "{")))
+         (rxt-m-to-n-brace-regexp
+          (rx-to-string
+           `(seq
+             (submatch (* (any "0-9"))) "," (submatch (+ (any "0-9")))
+             ,escape "}")))
+         (rxt-m-to-?-brace-regexp
+          (rx-to-string
+           `(seq (submatch (+ (any "0-9"))) "," ,escape "}")))
+         (rxt-m-brace-regexp
+          (rx-to-string
+           `(seq (submatch (+ (any "0-9"))) ,escape "}")))
+
+         ;; Named character classes [: ... :] differ slightly
+         (rxt-named-classes-regexp
+          (if pcre-p
+              rxt-pcre-named-classes-regexp
+            rxt-elisp-named-classes-regexp))
+
+         (rxt-subgroup-count 0)
+         (case-fold-search nil))
+    (with-temp-buffer
+      (insert re)
+      (goto-char (point-min))
+      (let ((rxt-source-text-string re))
+        (rxt-parse-exp)))))
+
+;; Parse a complete regex: a number of branches separated by | or
+;; \|, as determined by `rxt-branch-end-regexp'.
+(defun rxt-parse-exp ()
+  ;; These variables are let-bound here because in PCRE mode they may
+  ;; be set internally by (?x) or (?s) constructions, whose scope
+  ;; lasts until the end of a sub-expression
+  (rxt-with-source-location
+   (let ((rxt-pcre-extended-mode rxt-pcre-extended-mode)
+         (rxt-pcre-s-mode rxt-pcre-s-mode)
+         (rxt-pcre-case-fold rxt-pcre-case-fold))
+     (if (eobp)
+         (rxt-seq)
+       (let ((branches '()))
+         (cl-block nil
+           (while t
+             (let ((branch (rxt-parse-branch)))
+               (push branch branches)
+               (rxt-token-case
+                (rxt-choice-regexp nil)
+                (t (cl-return (apply #'rxt-choice (reverse branches)))))))))))))
+
+;; Skip over whitespace and comments in PCRE extended mode
+(defun rxt-extended-skip ()
+  (when rxt-pcre-extended-mode
+    (skip-syntax-forward "-")
+    (while (looking-at "#")
+      (beginning-of-line 2)
+      (skip-syntax-forward "-"))))
+
+;; Parse a regexp "branch": a sequence of pieces
+(defun rxt-parse-branch ()
+  (rxt-extended-skip)
+  (rxt-with-source-location
+   (let ((pieces '())
+         (branch-start-p t))
+     (while (not (looking-at rxt-branch-end-regexp))
+       (push (rxt-parse-piece branch-start-p) pieces)
+       (setq branch-start-p nil))
+     (apply #'rxt-seq (reverse pieces)))))
+
+;; Parse a regexp "piece": an atom (`rxt-parse-atom') plus any
+;; following quantifiers
+(defun rxt-parse-piece (&optional branch-begin)
+  (rxt-extended-skip)
+  (rxt-with-source-location
+   (let ((atom (rxt-parse-atom branch-begin)))
+     (rxt-parse-quantifiers atom))))
+
+;; Parse any and all quantifiers after ATOM and return the quantified
+;; regexp, or ATOM unchanged if no quantifiers
+(defun rxt-parse-quantifiers (atom)
+  (catch 'done
+    (while (not (eobp))
+      (let ((atom1 (rxt-parse-quantifier atom)))
+        (if (eq atom1 atom)
+            (throw 'done t)
+          (setq atom atom1)))))
+  atom)
+
+;; Possibly parse a single quantifier after ATOM and return the
+;; quantified atom, or ATOM if no quantifier
+(defun rxt-parse-quantifier (atom)
+  (rxt-extended-skip)
+  (rxt-token-case
+   ((rx "*?") (rxt-repeat 0 nil atom nil))
+   ((rx "*")  (rxt-repeat 0 nil atom t))
+   ((rx "+?") (rxt-repeat 1 nil atom nil))
+   ((rx "+")  (rxt-repeat 1 nil atom t))
+   ((rx "??") (rxt-repeat 0 1 atom nil))
+   ((rx "?")  (rxt-repeat 0 1 atom t))
+   ;; Brace expression "{M,N}", "{M,}", "{M}"
+   (rxt-brace-begin-regexp
+    (cl-destructuring-bind (from to)
+        (rxt-parse-braces)
+      (rxt-repeat from to atom)))
+   ;; No quantifiers found
+   (t atom)))
+
+;; Parse a regexp atom, i.e. an element that binds to any following
+;; quantifiers. This includes characters, character classes,
+;; parenthesized groups, assertions, etc.
+(defun rxt-parse-atom (&optional branch-begin)
+  (if (eobp)
+      (rxt-error "Unexpected end of regular expression")
+    (if rxt-parse-pcre
+        (rxt-parse-atom/pcre)
+      (rxt-parse-atom/el branch-begin))))
+
+(defun rxt-parse-atom/common ()
+  (rxt-token-case
+   ((rx "[")   (rxt-parse-char-class))
+   ((rx "\\b") (rxt-word-boundary))
+   ((rx "\\B") (rxt-not-word-boundary))))
+
+(defun rxt-parse-atom/el (branch-begin)
+  (rxt-with-source-location
+   (or (rxt-parse-atom/common)
+       (rxt-token-case
+        ;; "." wildcard
+        ((rx ".") (rxt-nonl))
+        ;; "^" and "$" are metacharacters only at beginning or end of a
+        ;; branch in Elisp; elsewhere they are literals
+        ((rx "^")
+         (if branch-begin
+             (rxt-bol)
+           (rxt-string "^")))
+        ((rx "$")
+         (if (looking-at rxt-branch-end-regexp)
+             (rxt-eol)
+           (rxt-string "$")))
+        ;; Beginning & end of string, word, symbol
+        ((rx "\\`") (rxt-bos))
+        ((rx "\\'") (rxt-eos))
+        ((rx "\\<") (rxt-bow))
+        ((rx "\\>") (rxt-eow))
+        ((rx "\\_<") (rxt-symbol-start))
+        ((rx "\\_>") (rxt-symbol-end))
+        ;; Subgroup
+        ((rx "\\(") (rxt-parse-subgroup/el))
+        ;; Word/non-word characters (meaning depending on syntax table)
+        ((rx "\\w") (rxt-wordchar))
+        ((rx "\\W") (rxt-not-wordchar))
+        ;; Other syntax categories
+        ((rx "\\" (submatch (any ?S ?s)) (submatch nonl))
+         (let ((negated (string= (match-string 1) "S"))
+               (syntax
+                (car (rassoc (string-to-char (match-string 2))
+                              rx-syntax))))
+           (if syntax
+               (let ((re (rxt-syntax-class syntax)))
+                 (if negated (rxt-negate re) re))
+             (rxt-error "Invalid syntax class `\\%s'" (match-string 0)))))
+        ;; Character categories
+        ((rx "\\" (submatch (any ?C ?c)) (submatch nonl))
+         (let ((negated (string= (match-string 1) "C"))
+               (category
+                (car (rassoc (string-to-char (match-string 2))
+                             rx-categories))))
+           (if category
+               (let ((re (rxt-char-category category)))
+                 (if negated (rxt-negate re) re))
+             (rxt-error "Invalid character category `%s'" (match-string 0)))))
+        ;; Backreference
+        ((rx (seq "\\" (submatch (any "1-9"))))
+         (rxt-backref (string-to-number (match-string 1))))
+        ;; Other escaped characters
+        ((rx (seq "\\" (submatch nonl)))
+         (rxt-string (match-string 1)))
+        ;; Normal characters
+        ((rx (or "\n" nonl))
+         (rxt-string (match-string 0)))))))
+
+(defun rxt-parse-atom/pcre ()
+  (rxt-extended-skip)
+  (rxt-with-source-location
+   (or
+    ;; Is it an atom that's the same in Elisp?
+    (rxt-parse-atom/common)
+    ;; Is it common to PCRE regex and character class syntax?
+    (let ((char (rxt-parse-escapes/pcre)))
+      (and char
+           (rxt-string (char-to-string char))))
+    ;; Otherwise:
+    (rxt-token-case
+     ;; "." wildcard
+     ((rx ".")
+      (if rxt-pcre-s-mode
+          (rxt-anything)
+        (rxt-nonl)))
+     ;; Beginning & end of string/line
+     ((rx "^") (rxt-bol))
+     ((rx "$") (rxt-eol))
+     ((rx "\\A") (rxt-bos))
+     ((rx "\\Z") (rxt-eos))
+     ;; Subgroup
+     ((rx "(") (rxt-parse-subgroup/pcre))
+     ;; Metacharacter quoting
+     ((rx "\\Q")
+      ;; It would seem simple to take all the characters between \Q
+      ;; and \E and make an rxt-string, but \Q...\E isn't an atom:
+      ;; any quantifiers afterward should bind only to the last
+      ;; character, not the whole string.
+      (let ((begin (point)))
+        (search-forward "\\E" nil t)
+        (let* ((end (match-beginning 0))
+               (str (buffer-substring-no-properties begin (1- end)))
+               (char (char-to-string (char-before end))))
+          (rxt-seq (rxt-string str)
+                   (rxt-parse-quantifiers (rxt-string char))))))
+     ;; Pre-defined character sets
+     ((rx "\\" (submatch (any "d" "D" "h" "H" "s" "S" "v" "V" "w" "W")))
+      (rxt--pcre-char-set (string-to-char (match-string 1))))
+     ;; \ + digits: backreference or octal char?
+     ((rx "\\" (submatch (+ (any "0-9"))))
+      (let* ((digits (match-string 1))
+             (dec (string-to-number digits)))
+        ;; from "man pcrepattern": If the number is less than 10, or if
+        ;; there have been at least that many previous capturing left
+        ;; parentheses in the expression, the entire sequence is taken
+        ;; as a back reference.
+        (if (and (> dec 0)
+                 (or (< dec 10)
+                     (>= rxt-subgroup-count dec)))
+            (progn
+              (when rxt-pcre-case-fold
+                (display-warning
+                 'rxt "Backreferences with case-folding are handled poorly"))
+              (rxt-backref dec))
+          ;; from "man pcrepattern": if the decimal number is greater
+          ;; than 9 and there have not been that many capturing
+          ;; subpatterns, PCRE re-reads up to three octal digits
+          ;; following the backslash, and uses them to generate a data
+          ;; character. Any subsequent digits stand for themselves.
+          (goto-char (match-beginning 1))
+          (re-search-forward (rx (** 0 3 (any "0-7"))))
+          (rxt-string (char-to-string (string-to-number (match-string 0) 8))))))
+     ;; Other escaped characters
+     ((rx "\\" (submatch nonl)) (rxt-string (match-string 1)))
+     ;; Everything else
+     ((rx (or (any "\n") nonl)) (rxt-string (match-string 0)))))))
+
+(defun rxt-parse-escapes/pcre ()
+  "Consume a one-char PCRE escape at point and return its codepoint equivalent.
+
+Handles only those character escapes which have the same meaning
+in character classes as outside them."
+  (rxt-token-case
+   ((rx "\\a") #x07) ; bell
+   ((rx "\\e") #x1b) ; escape
+   ((rx "\\f") #x0c) ; formfeed
+   ((rx "\\n") #x0a) ; linefeed
+   ((rx "\\r") #x0d) ; carriage return
+   ((rx "\\t") #x09) ; tab
+   ;; Control character
+   ((rx "\\c" (submatch nonl))
+    ;; from `man pcrepattern':
+    ;; The precise effect of \cx is as follows: if x is a lower case
+    ;; letter, it is converted to upper case.  Then bit 6 of the
+    ;; character (hex 40) is inverted.
+    (logxor (string-to-char (upcase (match-string 1))) #x40))
+   ;; Hex escapes
+   ((rx "\\x" (submatch (** 1 2 (any "0-9" "A-Z" "a-z"))))
+    (string-to-number (match-string 1) 16))
+   ((rx "\\x{" (submatch (* (any "0-9" "A-Z" "a-z"))) "}")
+    (string-to-number (match-string 1) 16))))
+
+(defun rxt-parse-subgroup/pcre ()
+  (catch 'return
+    (let ((shy nil)
+          (extended-mode rxt-pcre-extended-mode)
+          (single-line-mode rxt-pcre-s-mode)
+          (case-fold rxt-pcre-case-fold))
+      (rxt-extended-skip)
+      ;; Check for special (? ..) and (* ...) syntax
+      (rxt-token-case
+       ((rx "?")                        ; (?
+        (rxt-token-case
+         ((rx ")")                      ; Empty group (?)
+          (throw 'return (rxt-empty-string)))
+         (":" (setq shy t))             ; Shy group (?:
+         ("#"                           ; Comment   (?#
+          (search-forward ")")
+          (throw 'return (rxt-empty-string)))
+         ((rx (or                       ; Flags     (?isx-isx
+               (seq (group (* (any "gimosx"))) "-" (group (+ (any "gimosx"))))
+               (seq (group (+ (any "gimosx"))))))
+          (let ((token (match-string 0))
+                (on (or (match-string 1) (match-string 3)))
+                (off (or (match-string 2) "")))
+            (if (cl-find ?x on)  (setq extended-mode t))
+            (if (cl-find ?s on)  (setq single-line-mode t))
+            (if (cl-find ?i on)  (setq case-fold t))
+            (if (cl-find ?x off) (setq extended-mode nil))
+            (if (cl-find ?s off) (setq single-line-mode nil))
+            (if (cl-find ?i off) (setq case-fold nil))
+            (when (string-match-p "[gmo]" token)
+              (display-warning
+               'rxt (format "Unhandled PCRE flags in (?%s" token))))
+          (rxt-token-case
+           (":" (setq shy t))        ; Shy group with flags (?isx-isx: ...
+           (")"                      ; Set flags (?isx-isx)
+            ;; Set flags for the remainder of the current subexpression
+            (setq rxt-pcre-extended-mode extended-mode
+                  rxt-pcre-s-mode single-line-mode
+                  rxt-pcre-case-fold case-fold)
+            (throw 'return (rxt-empty-string)))))
+         ;; Other constructions like (?=, (?!, etc. are not recognised
+         (t (rxt-error "Unrecognized PCRE extended construction `(?%c'"
+                       (char-after)))))
+
+       ;; No special (* ...) verbs are recognised
+       ((rx "*")
+        (let ((begin (point)))
+          (search-forward ")" nil 'go-to-end)
+          (rxt-error "Unrecognized PCRE extended construction `(*%s'"
+                     (buffer-substring begin (point))))))
+
+      ;; Parse the remainder of the subgroup
+      (unless shy (cl-incf rxt-subgroup-count))
+      (let* ((rxt-pcre-extended-mode extended-mode)
+             (rxt-pcre-s-mode single-line-mode)
+             (rxt-pcre-case-fold case-fold)
+             (rx (rxt-parse-exp)))
+        (rxt-extended-skip)
+        (rxt-token-case
+         (")" (if shy rx (rxt-submatch rx)))
+         (t (rxt-error "Subexpression missing close paren")))))))
+
+(defun rxt-parse-subgroup/el ()
+  (let ((kind
+         (rxt-token-case
+          ((rx "?:")
+           (cl-incf rxt-subgroup-count)
+           'shy)
+          ((rx "?" (group (+ (in "0-9"))) ":")
+           (let ((n (string-to-number (match-string 1))))
+             (when (< rxt-subgroup-count n)
+               (setf rxt-subgroup-count n))
+             n))
+          ((rx "?") ; Reserved
+           (rxt-error "Unknown match group sequence")))))
+    (let ((rx (rxt-parse-exp)))
+      (rxt-token-case
+       ((rx "\\)")
+        (cond ((eq kind 'shy) rx)
+              ((numberp kind)
+               (rxt-submatch-numbered kind rx))
+              (t (rxt-submatch rx))))
+       (t (rxt-error "Subexpression missing close paren"))))))
+
+(defun rxt-parse-braces ()
+  (rxt-token-case
+   (rxt-m-to-n-brace-regexp
+    (list (string-to-number (match-string 1))
+          (string-to-number (match-string 2))))
+   (rxt-m-to-?-brace-regexp
+    (list (string-to-number (match-string 1)) nil))
+   (rxt-m-brace-regexp
+    (let ((a (string-to-number (match-string 1))))
+      (list a a)))
+   (t
+    (let ((begin (point)))
+      (search-forward "}" nil 'go-to-end)
+      (rxt-error "Bad brace expression {%s"
+                 (buffer-substring-no-properties begin (point)))))))
+
+;; Parse a character set range [...]
+(defun rxt-parse-char-class ()
+  (when (eobp)
+    (rxt-error "Missing close right bracket in regexp"))
+  (rxt-with-source-location
+   (let* ((negated (rxt-token-case
+                    ((rx "^") t)
+                    (t nil)))
+          (begin (point))
+          (result
+           (if negated
+               (rxt-negate (rxt-char-set-union))
+             (rxt-char-set-union)))
+          (transformer
+           (if negated #'rxt-negate #'identity))
+          (builder
+           (if negated #'rxt-char-set-intersection #'rxt-choice)))
+     (catch 'done
+       (while t
+         (when (eobp)
+           (rxt-error "Missing close right bracket in regexp"))
+         (if (and (looking-at (rx "]"))
+                  (not (= (point) begin)))
+             (throw 'done result)
+           (let ((piece (funcall transformer (rxt-parse-char-class-piece))))
+             (setq result (funcall builder result piece))))))
+     (forward-char)                     ; Skip over closing "]"
+     result)))
+
+;; Parse a single character, a character range, or a posix class
+;; within a character set context.  Returns an `rxt-char-set'.
+(defun rxt-parse-char-class-piece ()
+  (let ((atom (rxt-parse-char-class-atom)))
+    (cl-typecase atom
+      (rxt-char-set                     ; return unchanged
+       atom)
+      (integer                          ; character: check for range
+       (let ((range-end (rxt-maybe-parse-range-end)))
+         (if range-end
+             (rxt-char-set-union (cons atom range-end))
+           (rxt-char-set-union atom))))
+      (t                                ; transform into character set
+       (rxt-char-set-union atom)))))
+
+;; Parse a single character or named class within a charset.
+;;
+;; Returns an integer (a character), a symbol (representing a named
+;; character class) or an `rxt-char-set' (for pre-defined character
+;; classes like \d, \W, etc.)
+(defun rxt-parse-char-class-atom ()
+  (or
+   ;; First, check for PCRE-specific backslash sequences
+   (and rxt-parse-pcre
+        (rxt-parse-char-class-atom/pcre))
+   ;; Char-class syntax
+   (rxt-token-case
+    ;; Named classes [:alnum:], ...
+    (rxt-named-classes-regexp
+     (intern (match-string 1)))
+    ;; Error on unknown posix-class-like syntax
+    ((rx "[:" (* (any "a-z")) ":]")
+     (rxt-error "Unknown posix character class `%s'" (match-string 0)))
+    ;; Error on [= ... ]= collation syntax
+    ((rx "[" (submatch (any "." "="))
+         (* (any "a-z")) (backref 1) "]")
+     (rxt-error "Unsupported collation syntax `%s'" (match-string 0)))
+    ;; Other characters stand for themselves
+    ((rx (or "\n" nonl))
+     (string-to-char (match-string 0))))))
+
+;; Parse backslash escapes inside PCRE character classes
+(defun rxt-parse-char-class-atom/pcre ()
+  (or (rxt-parse-escapes/pcre)
+      (rxt-token-case
+       ;; Backslash + digits => octal char
+       ((rx "\\" (submatch (** 1 3 (any "0-7"))))
+        (string-to-number (match-string 1) 8))
+       ;; Pre-defined character sets
+       ((rx "\\" (submatch (any "d" "D" "h" "H" "s" "S" "v" "V" "w" "W")))
+        (rxt--pcre-char-set (string-to-char (match-string 1))))
+       ;; "\b" inside character classes is a backspace
+       ((rx "\\b") ?\C-h)
+       ;; Ignore other escapes
+       ((rx "\\" (submatch nonl))
+        (string-to-char (match-string 1))))))
+
+;; Look for a range tail (the "-z" in "a-z") after parsing a single
+;; character within in a character set.  Returns either a character
+;; representing the range end, or nil.
+(defun rxt-maybe-parse-range-end ()
+  (let ((range-end nil) (end-position nil))
+    (when (looking-at (rx "-" (not (any "]"))))
+      (save-excursion
+        (forward-char)
+        (setq range-end (rxt-parse-char-class-atom)
+              end-position (point))))
+
+    (if (characterp range-end)
+        ;; This is a range: move point after it and return the ending character
+        (progn
+          (goto-char end-position)
+          range-end)
+      ;; Not a range.
+      nil)))
+
+;; Return the pre-defined PCRE char-set associated with CHAR: i.e. \d
+;; is digits, \D non-digits, \s space characters, etc.
+(defun rxt--pcre-char-set (char)
+  (let* ((base-char (downcase char))
+         (negated (/= char base-char))
+         (elements (assoc-default base-char rxt-pcre-char-set-alist))
+         (base-char-set (apply #'rxt-char-set-union elements)))
+    (if negated
+        (rxt-negate base-char-set)
+      base-char-set)))
+
+\f
+;;;; Unparser to `rx' syntax
+
+(defconst rxt-rx-verbose-equivalents
+  '((bol . line-start)
+    (eol . line-end)
+    (nonl . not-newline)
+    (bos . string-start)
+    (eos . string-end)
+    (bow . word-start)
+    (eow . word-end)
+    (seq . sequence))
+  "Alist of verbose equivalents for short `rx' primitives.")
+
+(defun rxt-rx-symbol (sym)
+  (if rxt-verbose-rx-translation
+      (or (assoc-default sym rxt-rx-verbose-equivalents)
+          sym)
+    sym))
+
+(defun rxt-adt->rx (re)
+  (let ((rx
+         (cl-typecase re
+          (rxt-primitive
+           (rxt-rx-symbol (rxt-primitive-rx re)))
+
+          (rxt-string
+           (if (or (not (rxt-string-case-fold re))
+                   (string= "" (rxt-string-chars re)))
+               (rxt-string-chars re)
+             `(seq
+               ,@(cl-loop for char across (rxt-string-chars re)
+                          collect `(any ,(upcase char) ,(downcase char))))))
+
+          (rxt-seq
+           `(seq ,@(mapcar #'rxt-adt->rx (rxt-seq-elts re))))
+
+          (rxt-choice
+           `(or ,@(mapcar #'rxt-adt->rx (rxt-choice-elts re))))
+
+          (rxt-submatch
+           (if (rxt-seq-p (rxt-submatch-body re))
+               `(submatch
+                 ,@(mapcar #'rxt-adt->rx (rxt-seq-elts (rxt-submatch-body re))))
+             `(submatch ,(rxt-adt->rx (rxt-submatch-body re)))))
+
+          (rxt-submatch-numbered
+           (if (rxt-seq-p (rxt-submatch-numbered-p re))
+               `(,(rxt-rx-symbol 'submatch-n)
+                  ,(rxt-submatch-numbered-n re)
+                  ,@(mapcar #'rxt-adt->rx
+                            (rxt-seq-elts
+                             (rxt-submatch-numbered-body re))))
+             `(,(rxt-rx-symbol 'submatch-n)
+                ,(rxt-submatch-numbered-n re)
+                ,(rxt-adt->rx (rxt-submatch-numbered-body re)))))
+
+          (rxt-backref
+           (let ((n (rxt-backref-n re)))
+             (if (<= n 9)
+                 `(backref ,(rxt-backref-n re))
+               (rxt-error "Too many backreferences (%s)" n))))
+
+          (rxt-syntax-class
+           `(syntax ,(rxt-syntax-class-symbol re)))
+
+          (rxt-char-category
+           `(category ,(rxt-char-category-symbol re)))
+
+          (rxt-repeat
+           (let ((from (rxt-repeat-from re))
+                 (to (rxt-repeat-to re))
+                 (greedy (rxt-repeat-greedy re))
+                 (body (rxt-adt->rx (rxt-repeat-body re))))
+             (if rxt-verbose-rx-translation
+                 (let ((rx
+                        (cond
+                          ((and (zerop from) (null to))
+                           `(zero-or-more ,body))
+                          ((and (equal from 1) (null to))
+                           `(one-or-more ,body))
+                          ((and (zerop from) (equal to 1))
+                           `(zero-or-one ,body))
+                          ((null to)
+                           `(>= ,from ,body))
+                          ((equal from to)
+                           `(repeat ,from ,body))
+                          (t
+                           `(** ,from ,to ,body)))))
+                   (if greedy
+                       (if rxt-explain
+                           rx           ; Readable but not strictly accurate. Fixme?
+                         `(maximal-match ,rx))
+                     `(minimal-match ,rx)))
+               (cond
+                 ((and (zerop from) (null to))
+                  `(,(if greedy '* '*?) ,body))
+                 ((and (equal from 1) (null to))
+                  `(,(if greedy '+ '+?) ,body))
+                 ((and (zerop from) (equal to 1))
+                  `(,(if greedy ? ??) ,body))
+                 ((null to)
+                  `(>= ,from ,body))
+                 ((equal from to)
+                  `(= ,from ,body))
+                 (t
+                  `(** ,from ,to ,body))))))
+
+          (rxt-char-set-union
+           (let* ((case-fold (rxt-char-set-union-case-fold re))
+                  (re (rxt--simplify-char-set re case-fold))
+                  (chars (rxt-char-set-union-chars re))
+                  (ranges (rxt-char-set-union-ranges re))
+                  (classes (rxt-char-set-union-classes re))
+                  (case-fold (rxt-char-set-union-case-fold re)))
+             (if (and (null chars) (null ranges) (= 1 (length classes)))
+                 (car classes)
+               `(any ,@chars ,@ranges ,@classes))))
+
+          (rxt-char-set-negation
+           `(not ,(rxt-adt->rx (rxt-char-set-negation-elt re))))
+
+          (t
+           (rxt-error "No RX translation of `%s'" (rxt-to-string re))))))
+
+    ;; Store source information on each fragment of the generated RX
+    ;; sexp for rxt-explain mode
+    (when rxt-explain
+      ;; Use gensyms to store unique source information for multiple
+      ;; occurrences of primitives like `bol'
+      (when (symbolp rx)
+        (setq rx (make-symbol (symbol-name rx))))
+      (setf (rxt-location rx) (rxt-location re)))
+    rx))
+
+\f
+;;;; 'Unparser' to PCRE notation
+
+;;; Based on scsh/posixstr.scm in scsh
+
+;; To ensure that the operator precedence in the generated regexp does
+;; what we want, we need to keep track of what kind of production is
+;; returned from each step. Therefore these functions return a string
+;; and a numeric "level" which lets the function using the generated
+;; regexp know whether it has to be parenthesized:
+;;
+;; 0: an already parenthesized expression
+;;
+;; 1: a "piece" binds to any succeeding quantifiers
+;;
+;; 2: a "branch", or concatenation of pieces, needs parenthesizing to
+;; bind to quantifiers
+;;
+;; 3: a "top", or alternation of branches, needs parenthesizing to
+;; bind to quantifiers or to concatenation
+;;
+;; This idea is stolen straight out of the scsh implementation.
+
+(defun rxt-adt->pcre (re)
+  (cl-destructuring-bind (s _) (rxt-adt->pcre/lev re) s))
+
+(defun rxt-adt->pcre/lev (re)
+  (cl-typecase re
+    (rxt-primitive
+     (let ((s (rxt-primitive-pcre re)))
+       (if s
+           (list s 1)
+         (rxt-error "No PCRE translation of `%s'" (rxt-to-string re)))))
+
+   (rxt-string (rxt-string->pcre re))
+   (rxt-seq (rxt-seq->pcre re))
+   (rxt-choice (rxt-choice->pcre re))
+   (rxt-submatch (rxt-submatch->pcre re))
+   (rxt-backref
+    (list (format "\\%d" (rxt-backref-n re)) 1))
+   (rxt-repeat (rxt-repeat->pcre re))
+
+   ((or rxt-char-set-union rxt-char-set-negation)
+    (rxt-char-set->pcre re))
+   
+   ;; FIXME
+   ;; ((rxt-char-set-intersection re) (rxt-char-set-intersection->pcre re))
+
+   (t
+    (rxt-error "No PCRE translation of `%s'" (rxt-to-string re)))))
+
+(defconst rxt-pcre-metachars (rx (any "\\^.$|()[]*+?{}")))
+(defconst rxt-pcre-charset-metachars (rx (any "]" "[" "\\" "^" "-")))
+
+(defun rxt-string->pcre (re)
+  (let ((chars (rxt-string-chars re)))
+    (list
+     (replace-regexp-in-string
+      rxt-pcre-metachars
+      "\\\\\\&" chars)
+     ;; A one-character string is a 'piece' (it binds to a following
+     ;; quantifier).  A longer string is a 'branch' (it has to be
+     ;; enclosed in parentheses to bind to a following quantifier).
+     (if (> (length chars) 1) 2 1))))
+
+(defun rxt-seq->pcre (re)
+  (let ((elts (rxt-seq-elts re)))
+    (if (null elts)
+        ""
+      (rxt-seq-elts->pcre elts))))
+
+(defun rxt-seq-elts->pcre (elts)
+  (cl-destructuring-bind
+      (s lev) (rxt-adt->pcre/lev (car elts))
+    (if (null (cdr elts))
+        (list s lev)
+      (cl-destructuring-bind
+          (s1 lev1) (rxt-seq-elts->pcre (cdr elts))
+        (list (concat (rxt-paren-if-necessary s lev)
+                      (rxt-paren-if-necessary s1 lev1))
+              2)))))
+
+(defun rxt-paren-if-necessary (s lev)
+  (if (< lev 3)
+      s
+    (concat "(?:" s ")")))
+
+(defun rxt-choice->pcre (re)
+  (let ((elts (rxt-choice-elts re)))
+    (if (null elts)
+        nil
+      (rxt-choice-elts->pcre elts))))
+
+(defun rxt-choice-elts->pcre (elts)
+  (cl-destructuring-bind
+      (s lev) (rxt-adt->pcre/lev (car elts))
+    (if (null (cdr elts))
+        (list s lev)
+      (cl-destructuring-bind
+          (s1 lev1) (rxt-choice-elts->pcre (cdr elts))
+        (list (concat s "|" s1) 3)))))
+
+(defun rxt-submatch->pcre (re)
+  (cl-destructuring-bind
+      (s lev) (rxt-adt->pcre/lev (rxt-submatch-body re))
+    (list (concat "(" s ")") 0)))
+
+(defun rxt-repeat->pcre (re)
+  (let ((from (rxt-repeat-from re))
+        (to (rxt-repeat-to re))
+        (body (rxt-repeat-body re))
+        (greedy (rxt-repeat-greedy re)))
+    (cl-destructuring-bind
+        (s lev) (rxt-adt->pcre/lev body)
+      (cond
+       ((and to (= from 1) (= to 1)) (list s lev))
+       ((and to (= from 0) (= to 0)) (list "" 2))
+       (t
+        (when (> lev 1)     ; parenthesize non-atoms
+          (setq s (concat "(?:" s ")")
+                lev 0))
+        (list (if to
+                  (cond ((and (= from 0) (= to 1))
+                         (concat s (if greedy "?" "??")))
+                        ((= from to)
+                         (concat s "{" (number-to-string to) "}"))
+                        (t
+                         (concat s "{" (number-to-string from)
+                                 "," (number-to-string to) "}")))
+                (cond ((= from 0)
+                       (concat s (if greedy "*" "*?")))
+                      ((= from 1)
+                       (concat s (if greedy "+" "+?")))
+                      (t (concat s "{" (number-to-string from) ",}"))))
+              1))))))
+
+(defun rxt-char-set->pcre (re)
+  (cond ((rxt-char-set-union-p re)
+         (list
+          (concat "[" (rxt-char-set->pcre/chars re) "]") 1))
+
+        ((rxt-char-set-negation-p re)
+         (let ((elt (rxt-char-set-negation-elt re)))
+           (if (rxt-char-set-union-p elt)
+               (list
+                (concat "[^" (rxt-char-set->pcre/chars elt) "]") 1)
+             (rxt-error "No PCRE translation of `%s'" (rxt-to-string elt)))))
+
+        (t
+         (rxt-error "Non-char-set in rxt-char-set->pcre: %s" re))))
+
+;; Fortunately, easier in PCRE than in POSIX!
+(defun rxt-char-set->pcre/chars (re)
+  (cl-flet
+      ((escape
+        (char)
+        (let ((s (char-to-string char)))
+          (cond ((string-match rxt-pcre-charset-metachars s)
+                 (concat "\\" s))
+
+                ((and (not (string= s " "))
+                      (string-match "[^[:graph:]]" s))
+                 (format "\\x{%x}" char))
+
+                (t s)))))
+
+    (let ((chars (rxt-char-set-union-chars re))
+          (ranges (rxt-char-set-union-ranges re))
+          (classes (rxt-char-set-union-classes re)))
+
+      (concat
+       (mapconcat #'escape chars "")
+       (mapconcat #'(lambda (rg)
+                      (format "%s-%s"
+                              (escape (car rg))
+                              (escape (cdr rg))))
+                  ranges "")
+       (mapconcat #'(lambda (class)
+                      (format "[:%s:]" class))
+                  classes "")))))
+
+\f
+;;;; Generate all productions of a finite regexp
+
+(defun rxt-adt->strings (re)
+  (cl-typecase re
+    (rxt-primitive
+     (list ""))
+    (rxt-string
+     (list (rxt-string-chars re)))
+    (rxt-seq
+     (rxt-seq-elts->strings (rxt-seq-elts re)))
+    (rxt-choice
+     (rxt-choice-elts->strings (rxt-choice-elts re)))
+    (rxt-submatch
+     (rxt-adt->strings (rxt-submatch-body re)))
+    (rxt-submatch-numbered
+     (rxt-adt->strings (rxt-submatch-numbered-body re)))
+    (rxt-repeat
+     (rxt-repeat->strings re))
+    (rxt-char-set-union
+     (rxt-char-set->strings re))
+    (t
+     (error "Can't generate productions of %s"
+            (rxt-syntax-tree-readable re)))))
+
+(defun rxt-concat-product (heads tails)
+  (cl-mapcan
+   (lambda (hs)
+     (mapcar
+      (lambda (ts) (concat hs ts))
+      tails))
+   heads))
+
+(defun rxt-seq-elts->strings (elts)
+  (if (null elts)
+      '("")
+    (let ((heads (rxt-adt->strings (car elts)))
+          (tails (rxt-seq-elts->strings (cdr elts))))
+      (rxt-concat-product heads tails))))
+
+(defun rxt-choice-elts->strings (elts)
+  (if (null elts)
+      '()
+    (append (rxt-adt->strings (car elts))
+            (rxt-choice-elts->strings (cdr elts)))))
+
+(defun rxt-repeat->strings (re)
+  (let ((from (rxt-repeat-from re))
+        (to (rxt-repeat-to re)))
+    (if (not to)
+        (error "Can't generate all productions of unbounded repeat \"%s\""
+               (rxt-syntax-tree-readable re))
+      (let ((strings (rxt-adt->strings (rxt-repeat-body re))))
+        (rxt-repeat-n-m->strings from to strings)))))
+
+(defun rxt-repeat-n-m->strings (from to strings)
+  (cond
+   ((zerop to) '(""))
+   ((= to from) (rxt-repeat-n->strings from strings))
+   (t           ; to > from
+    (let* ((strs-n (rxt-repeat-n->strings from strings))
+           (accum (cl-copy-list strs-n)))
+      (dotimes (i (- to from))
+        (setq strs-n (rxt-concat-product strs-n strings))
+        (setq accum (nconc accum strs-n)))
+      accum))))
+
+(defun rxt-repeat-n->strings (n strings)
+  ;; n > 1
+  (cond ((zerop n) '(""))
+        ((= n 1) strings)
+        (t
+         (rxt-concat-product
+          (rxt-repeat-n->strings (- n 1) strings)
+          strings))))
+
+(defun rxt-char-set->strings (re)
+  (if (rxt-char-set-union-classes re)
+      (error "Can't generate all productions of named character classes in \"%s\""
+             (rxt-syntax-tree-readable re))
+    (let ((chars (mapcar #'char-to-string (rxt-char-set-union-chars re))))
+      (dolist (range (rxt-char-set-union-ranges re))
+        (let ((end (cdr range)))
+          (cl-do ((i (car range) (+ i 1)))
+              ((> i end))
+            (push (char-to-string i) chars))))
+      chars)))
+
+\f
+;;;; RE-Builder hacks
+
+(defadvice reb-update-modestring
+  (after rxt () activate compile)
+  "This function is hacked for emulated PCRE syntax and regexp conversion."
+  (setq reb-mode-string
+        (concat
+         (format " (%s)" reb-re-syntax)
+         reb-mode-string))
+  (force-mode-line-update))
+
+(defadvice reb-change-syntax
+  (around rxt (&optional syntax) activate compile)
+  "This function is hacked for emulated PCRE syntax and regexp conversion."
+  (interactive
+   (list (intern
+          (completing-read (format "Select syntax (%s): " reb-re-syntax)
+                           '(read string pcre sregex rx)
+                           nil t "" nil (symbol-name reb-re-syntax)))))
+  (unless (memq syntax '(read string pcre lisp-re sregex rx))
+    (error "Invalid syntax: %s" syntax))
+  (let ((re-builder-buffer (get-buffer reb-buffer)))
+    (setq reb-re-syntax syntax)
+    (when re-builder-buffer
+      (with-current-buffer reb-target-buffer
+        (cl-case syntax
+          (rx
+           (let ((rx (rxt-elisp-to-rx reb-regexp)))
+             (setq reb-regexp-src
+                   (with-temp-buffer
+                     (insert "\n" "'")
+                     (rxt-print rx)
+                     (buffer-string)))))
+          (pcre
+           (setq reb-regexp-src (rxt-elisp-to-pcre reb-regexp)))))
+      (with-current-buffer re-builder-buffer
+        ;; Hack: prevent reb-auto-update from clobbering the
+        ;; reb-regexp-src we just set
+        (let ((inhibit-modification-hooks t))
+          (reb-initialize-buffer))
+        ;; Enable flag-toggling bindings for PCRE syntax
+        (rxt--re-builder-switch-pcre-mode)))))
+
+(defadvice reb-read-regexp
+  (around rxt () activate compile)
+  "This function is hacked for emulated PCRE syntax and regexp conversion."
+  (if (eq reb-re-syntax 'pcre)
+      (setq ad-return-value
+            (save-excursion
+              (goto-char (point-min))
+              (rxt-read-delimited-pcre)))
+    ad-do-it))
+
+(defadvice reb-insert-regexp
+  (around rxt () activate compile)
+  "This function is hacked for emulated PCRE syntax and regexp conversion."
+  (if (eq reb-re-syntax 'pcre)
+      (let ((src (reb-target-binding reb-regexp-src)))
+        (if src
+            (insert "\n/" (replace-regexp-in-string "/" "\\/" src t t) "/")
+          (insert "\n//")))
+    ad-do-it))
+
+(defadvice reb-cook-regexp
+  (around rxt (re) activate compile)
+  "This function is hacked for emulated PCRE syntax and regexp conversion."
+  (if (eq reb-re-syntax 'pcre)
+      (setq ad-return-value (rxt-pcre-to-elisp re))
+    ad-do-it))
+
+(defadvice reb-update-regexp
+  (around rxt () activate compile)
+  "This function is hacked for emulated PCRE syntax and regexp conversion."
+  (setq ad-return-value
+        (let* ((re-src (reb-read-regexp))
+               (re (reb-cook-regexp re-src)))
+          (with-current-buffer reb-target-buffer
+            (let ((oldre reb-regexp))
+              (prog1
+                  (not (string= oldre re))
+                (setq reb-regexp re)
+                ;; Update the source re if format requires translation
+                (when (or (reb-lisp-syntax-p) (eq reb-re-syntax 'pcre))
+                  (setq reb-regexp-src re-src))))))))
+
+(defun rxt--re-builder-switch-pcre-mode ()
+  (rxt--read-pcre-mode
+   (if (eq reb-re-syntax 'pcre) 1 0)))
+
+(add-hook 'reb-mode-hook #'rxt--re-builder-switch-pcre-mode)
+
+(provide 'rxt)
+(provide 'pcre2el)
+
+
+;;; pcre2el.el ends here
diff --git a/elpa/pcre2el-readme.txt b/elpa/pcre2el-readme.txt
new file mode 100644 (file)
index 0000000..0ad9a30
--- /dev/null
@@ -0,0 +1,381 @@
+1 Overview
+==========
+
+  `pcre2el' or `rxt' (RegeXp Translator or RegeXp Tools) is a utility
+  for working with regular expressions in Emacs, based on a
+  recursive-descent parser for regexp syntax. In addition to converting
+  (a subset of) PCRE syntax into its Emacs equivalent, it can do the
+  following:
+
+  - convert Emacs syntax to PCRE
+  - convert either syntax to `rx', an S-expression based regexp syntax
+  - untangle complex regexps by showing the parse tree in `rx' form and
+    highlighting the corresponding chunks of code
+  - show the complete list of strings (productions) matching a regexp,
+    provided the list is finite
+  - provide live font-locking of regexp syntax (so far only for Elisp
+    buffers -- other modes on the TODO list)
+
+
+2 Usage
+=======
+
+  Enable `rxt-mode' or its global equivalent `rxt-global-mode' to get
+  the default key-bindings. There are three sets of commands: commands
+  that take a PCRE regexp, commands which take an Emacs regexp, and
+  commands that try to do the right thing based on the current
+  mode. Currently, this means Emacs syntax in `emacs-lisp-mode' and
+  `lisp-interaction-mode', and PCRE syntax everywhere else.
+
+  The default key bindings all begin with `C-c /' and have a mnemonic
+  structure: `C-c / <source> <target>', or just `C-c / <target>' for the
+  "do what I mean" commands. The complete list of key bindings is given
+  here and explained in more detail below:
+
+  - "Do-what-I-mean" commands:
+    `C-c / /': `rxt-explain'
+    `C-c / c': `rxt-convert-syntax'
+    `C-c / x': `rxt-convert-to-rx'
+    `C-c / '': `rxt-convert-to-strings'
+
+  - Commands that work on a PCRE regexp:
+    `C-c / p e': `rxt-pcre-to-elisp'
+    `C-c / %': `pcre-query-replace-regexp'
+    `C-c / p x': `rxt-pcre-to-rx'
+    `C-c / p '': `rxt-pcre-to-strings'
+    `C-c / p /': `rxt-explain-pcre'
+
+  - Commands that work on an Emacs regexp:
+    `C-c / e /': `rxt-explain-elisp'
+    `C-c / e p': `rxt-elisp-to-pcre'
+    `C-c / e x': `rxt-elisp-to-rx'
+    `C-c / e '': `rxt-elisp-to-strings'
+    `C-c / e t': `rxt-toggle-elisp-rx'
+    `C-c / t': `rxt-toggle-elisp-rx'
+
+
+2.1 Interactive input and output
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+  When used interactively, the conversion commands can read a regexp
+  either from the current buffer or from the minibuffer. The output is
+  displayed in the minibuffer and copied to the kill-ring.
+
+  - When called with a prefix argument (`C-u'), they read a regular
+    expression from the minibuffer literally, without further processing
+    -- meaning there's no need to double the backslashes if it's an
+    Emacs regexp.  This is the same way commands like
+    `query-replace-regexp' read input.
+
+  - When the region is active, they use they the region contents, again
+    literally (without any translation of string syntax).
+
+  - With neither a prefix arg nor an active region, the behavior depends
+    on whether the command expects an Emacs regexp or a PCRE one.
+
+    Commands that take an Emacs regexp behave like `C-x C-e': they
+    evaluate the sexp before point (which could be simply a string
+    literal) and use its value. This is designed for use in Elisp
+    buffers. As a special case, if point is *inside* a string, it's
+    first moved to the string end, so in practice they should work as
+    long as point is somewhere within the regexp literal.
+
+    Commands that take a PCRE regexp try to read a Perl-style delimited
+    regex literal *after* point in the current buffer, including its
+    flags. For example, putting point before the `m' in the following
+    example and doing `C-c / p e' (`rxt-pcre-to-elisp') displays
+    `\(?:bar\|foo\)', correctly stripping out the whitespace and
+    comment:
+
+    ,----
+    | $x =~ m/  foo   |  (?# comment) bar /x
+    `----
+
+    The PCRE reader currently only works with `/ ... /' delimiters. It
+    will ignore any preceding `m', `s', or `qr' operator, as well as the
+    replacement part of an `s' construction.
+
+    Readers for other PCRE-using languages are on the TODO list.
+
+  The translation functions display their result in the minibuffer and
+  copy it to the kill ring. When translating something into Elisp
+  syntax, you might need to use the result either literally (e.g. for
+  interactive input to a command like `query-replace-regexp'), or as a
+  string to paste into Lisp code.  To allow both uses,
+  `rxt-pcre-to-elisp' copies both versions successively to the
+  kill-ring. The literal regexp without string quoting is the top
+  element of the kill-ring, while the Lisp string is the
+  second-from-top. You can paste the literal regexp somewhere by doing
+  `C-y', or the Lisp string by `C-y M-y'.
+
+
+2.2 Syntax conversion commands
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+  `rxt-convert-syntax' (`C-c / c') converts between Emacs and PCRE
+  syntax, depending on the major mode in effect when called.
+  Alternatively, you can specify the conversion direction explicitly by
+  using either `rxt-pcre-to-elisp' (`C-c / p e') or `rxt-elisp-to-pcre'
+  (`C-c / e p').
+
+  Similarly, `rxt-convert-to-rx' (`C-c / x') converts either kind of
+  syntax to `rx' form, while `rxt-convert-pcre-to-rx' (`C-c / p x') and
+  `rxt-convert-elisp-to-rx' (`C-c / e x') convert to `rx' from a
+  specified source type.
+
+  In Elisp buffers, you can use `rxt-toggle-elisp-rx' (`C-c / t' or `C-c
+  / e t') to switch the regexp at point back and forth between string
+  and `rx' syntax. Point should either be within an `rx' or
+  `rx-to-string' form or a string literal for this to work.
+
+
+2.3 PCRE mode (experimental)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+  If you want to use emulated PCRE regexp syntax in all Emacs commands,
+  try `pcre-mode', which uses Emacs's advice system to make all commands
+  that read regexps using the minibuffer use emulated PCRE syntax.  It
+  should also work with Isearch.
+
+  This feature is still fairly experimental.  It may fail to work or do
+  the wrong thing with certain commands.  Please report bugs.
+
+  `pcre-query-replace-regexp' was originally defined to do query-replace
+  using emulated PCRE regexps, and is now made somewhat obsolete by
+  `pcre-mode'.  It is bound to `C-c / %' by default, by analogy with
+  `M-%'.  Put the following in your `.emacs' if you want to use
+  PCRE-style query replacement everywhere:
+
+  ,----
+  | (global-set-key [(meta %)] 'pcre-query-replace-regexp)
+  `----
+
+2.5 Explain regexps
+~~~~~~~~~~~~~~~~~~~
+
+  When syntax-highlighting isn't enough to untangle some gnarly regexp
+  you find in the wild, try the 'explain' commands: `rxt-explain' (`C-c
+  / /'), `rxt-explain-pcre' (`C-c / p') and `rxt-explain-elisp' (`C-c /
+  e'). These display the original regexp along with its pretty-printed
+  `rx' equivalent in a new buffer.  Moving point around either in the
+  original regexp or the `rx' translation highlights corresponding
+  pieces of syntax, which can aid in seeing things like the scope of
+  quantifiers.
+
+  I call them "explain" commands because the `rx' form is close to a
+  plain syntax tree, and this plus the wordiness of the operators
+  usually helps to clarify what is going on.  People who dislike Lisp
+  syntax might disagree with this assessment.
+
+
+2.6 Generate all matching strings (productions)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+  Occasionally you come across a regexp which is designed to match a
+  finite set of strings, e.g. a set of keywords, and it would be useful
+  to recover the original set. (In Emacs you can generate such regexps
+  using `regexp-opt'). The commands `rxt-convert-to-strings' (`C-c /
+  ′'), `rxt-pcre-to-strings' (`C-c / p ′') or `rxt-elisp-to-strings'
+  (`C-c / e ′') accomplish this by generating all the matching strings
+  ("productions") of a regexp.  (The productions are copied to the kill
+  ring as a Lisp list).
+
+  An example in Lisp code:
+
+  ,----
+  | (regexp-opt '("cat" "caterpillar" "catatonic"))
+  |    ;; => "\\(?:cat\\(?:atonic\\|erpillar\\)?\\)"
+  | (rxt-elisp-to-strings "\\(?:cat\\(?:atonic\\|erpillar\\)?\\)")
+  |     ;; => '("cat" "caterpillar" "catatonic")
+  `----
+
+  For obvious reasons, these commands only work with regexps that don't
+  include any unbounded quantifiers like `+' or `*'. They also can't
+  enumerate all the characters that match a named character class like
+  `[[:alnum:]]'. In either case they will give a (hopefully meaningful)
+  error message. Due to the nature of permutations, it's still possible
+  for a finite regexp to generate a huge number of productions, which
+  will eat memory and slow down your Emacs. Be ready with `C-g' if
+  necessary.
+
+
+2.7 RE-Builder support
+~~~~~~~~~~~~~~~~~~~~~~
+
+  The Emacs RE-Builder is a useful visual tool which allows using
+  several different built-in syntaxes via `reb-change-syntax' (`C-c
+  TAB'). It supports Elisp read and literal syntax and `rx', but it can
+  only convert from the symbolic forms to Elisp, not the other way. This
+  package hacks the RE-Builder to also work with emulated PCRE syntax,
+  and to convert transparently between Elisp, PCRE and rx syntaxes. PCRE
+  mode reads a delimited Perl-like literal of the form `/ ... /', and it
+  should correctly support using the `x' and `s' flags.
+
+
+2.8 Use from Lisp
+~~~~~~~~~~~~~~~~~
+
+  Example of using the conversion functions:
+  ,----
+  | (rxt-pcre-to-elisp "(abc|def)\\w+\\d+")
+  |    ;; => "\\(\\(?:abc\\|def\\)\\)[_[:alnum:]]+[[:digit:]]+"
+  `----
+
+  All the conversion functions take a single string argument, the regexp
+  to translate:
+
+  - `rxt-pcre-to-elisp'
+  - `rxt-pcre-to-rx'
+  - `rxt-pcre-to-strings'
+  - `rxt-elisp-to-pcre'
+  - `rxt-elisp-to-rx'
+  - `rxt-elisp-to-strings'
+
+
+3 Bugs and Limitations
+======================
+
+3.1 Limitations on PCRE syntax
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+  PCRE has a complicated syntax and semantics, only some of which can be
+  translated into Elisp. The following subset of PCRE should be
+  correctly parsed and converted:
+
+  - parenthesis grouping `( .. )', including shy matches `(?: ... )'
+  - backreferences (various syntaxes), but only up to 9 per expression
+  - alternation `|'
+  - greedy and non-greedy quantifiers `*', `*?', `+', `+?', `?' and `??'
+          (all of which are the same in Elisp as in PCRE)
+  - numerical quantifiers `{M,N}'
+  - beginning/end of string `\A', `\Z'
+  - string quoting `\Q .. \E'
+  - word boundaries `\b', `\B' (these are the same in Elisp)
+  - single character escapes `\a', `\c', `\e', `\f', `\n', `\r', `\t',
+    `\x', and `\octal digits' (but see below about non-ASCII characters)
+  - character classes `[...]' including Posix escapes
+  - character classes `\d', `\D', `\h', `\H', `\s', `\S', `\v', `\V'
+          both within character class brackets and outside
+  - word and non-word characters `\w' and `\W' (Emacs has the same
+          syntax, but its meaning is different)
+  - `s' (single line) and `x' (extended syntax) flags, in regexp
+    literals, or set within the expression via `(?xs-xs)' or `(?xs-xs:
+    .... )' syntax
+  - comments `(?# ... )'
+
+  Most of the more esoteric PCRE features can't really be supported by
+  simple translation to Elisp regexps. These include the different
+  lookaround assertions, conditionals, and the "backtracking control
+  verbs" `(* ...)' . OTOH, there are a few other syntaxes which are
+  currently unsupported and possibly could be:
+
+  - `\L', `\U', `\l', `\u' case modifiers
+  - `\g{...}' backreferences
+
+
+3.2 Other limitations
+~~~~~~~~~~~~~~~~~~~~~
+
+  - The order of alternatives and characters in char classes sometimes
+    gets shifted around, which is annoying.
+  - Although the string parser tries to interpret PCRE's octal and
+    hexadecimal escapes correctly, there are problems with matching
+    8-bit characters that I don't use enough to properly understand,
+    e.g.:
+    ,----
+    | (string-match-p (rxt-pcre-to-elisp "\\377") "\377") => nil
+    `----
+    A fix for this would be welcome.
+
+  - Most of PCRE's rules for how `^', `\A', `$' and `\Z' interact with
+    newlines are not implemented, since they seem less relevant to
+    Emacs's buffer-oriented rather than line-oriented model.  However,
+    the different meanings of the `.' metacharacter *are* implemented
+    (it matches newlines with the `/s' flag, but not otherwise).
+
+  - Not currently namespace clean (both `rxt-' and a couple of `pcre-'
+    functions).
+
+
+3.3 TODO:
+~~~~~~~~~
+
+  - Python-specific extensions to PCRE?
+  - Language-specific stuff to enable regexp font-locking and explaining
+    in different modes. Each language would need two functions, which
+    could be kept in an alist:
+
+    1. A function to read PCRE regexps, taking the string syntax into
+       account. E.g., Python has single-quoted, double-quoted and raw
+       strings, each with different quoting rules.  PHP has the kind of
+       belt-and-suspenders solution you would expect: regexps are in
+       strings, /and/ you have to include the `/ ...  /' delimiters!
+       Duh.
+
+    2. A function to copy faces back from the parsed string to the
+       original buffer text. This has to recognize any escape sequences
+       so they can be treated as a single character.
+
+
+4 Internal details
+==================
+
+  `rxt' defines an internal syntax tree representation of regular
+  expressions, parsers for Elisp and PCRE syntax, and 'unparsers'
+  to convert the internal representation to PCRE or `rx' syntax.
+  Converting from the internal representation to Emacs syntax is
+  done by converting to `rx' form and passing it to `rx-to-string'.
+  See `rxt-parse-re', `rxt-adt->pcre', and `rxt-adt->rx' for
+  details.
+
+  This code is partially based on Olin Shivers' reference SRE
+  implementation in scsh, although it is simplified in some respects and
+  extended in others. See `scsh/re.scm', `scsh/spencer.scm' and
+  `scsh/posixstr.scm' in the `scsh' source tree for details. In
+  particular, `pcre2el' steals the idea of an abstract data type for
+  regular expressions and the general structure of the string regexp
+  parser and unparser. The data types for character sets are extended in
+  order to support symbolic translation between character set
+  expressions without assuming a small (Latin1) character set. The
+  string parser is also extended to parse a bigger variety of
+  constructions, including POSIX character classes and various Emacs and
+  Perl regexp assertions. Otherwise, only the bare minimum of scsh's
+  abstract data type is implemented.
+
+
+5 Soapbox
+=========
+
+  Emacs regexps have their annoyances, but it is worth getting used to
+  them. The Emacs assertions for word boundaries, symbol boundaries, and
+  syntax classes depending on the syntax of the mode in effect are
+  especially useful. (PCRE has `\b' for word-boundary, but AFAIK it
+  doesn't have separate assertions for beginning-of-word and
+  end-of-word). Other things that might be done with huge regexps in
+  other languages can be expressed more understandably in Elisp using
+  combinations of `save-excursion' with the various searches (regexp,
+  literal, skip-syntax-forward, sexp-movement functions, etc.).
+
+  There's not much point in using `rxt-pcre-to-elisp' to use PCRE
+  notation in a Lisp program you're going to maintain, since you still
+  have to double all the backslashes.  Better to just use the converted
+  result (or better yet, the `rx' form).
+
+
+6 History and acknowledgments
+=============================
+
+  This was originally created out of an answer to a stackoverflow
+  question:
+  [http://stackoverflow.com/questions/9118183/elisp-mechanism-for-converting-pcre-regexps-to-emacs-regexps]
+
+  Thanks to:
+
+  - Wes Hardaker (hardaker) for the initial inspiration and subsequent
+    hacking
+  - priyadarshan for requesting RX support
+  - Daniel Colascione (dcolascione) for a patch to support Emacs's
+    explicitly-numbered match groups
+  - Aaron Meurer (asmeurer) for requesting Isearch support
+  - Philippe Vaucher (silex) for a patch to support `ibuffer-do-replace-regexp'
+    in PCRE mode
diff --git a/elpa/sesman-20190909.1754/sesman-autoloads.el b/elpa/sesman-20190909.1754/sesman-autoloads.el
new file mode 100644 (file)
index 0000000..8485ba7
--- /dev/null
@@ -0,0 +1,98 @@
+;;; sesman-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
+\f
+;;;### (autoloads nil "sesman" "sesman.el" (23997 31641 490594 106000))
+;;; Generated autoloads from sesman.el
+
+(autoload 'sesman-start "sesman" "\
+Start a Sesman session.
+
+\(fn)" t nil)
+
+(autoload 'sesman-restart "sesman" "\
+Restart sesman session.
+When WHICH is nil, restart the current session; when a single universal
+argument or 'linked, restart all linked sessions; when a double universal
+argument, t or 'all, restart all sessions. For programmatic use, WHICH can also
+be a session or a name of the session, in which case that session is restarted.
+
+\(fn &optional WHICH)" t nil)
+
+(autoload 'sesman-quit "sesman" "\
+Terminate a Sesman session.
+When WHICH is nil, kill only the current session; when a single universal
+argument or 'linked, kill all linked sessions; when a double universal argument,
+t or 'all, kill all sessions. For programmatic use, WHICH can also be a session
+or a name of the session, in which case that session is killed.
+
+\(fn &optional WHICH)" t nil)
+
+(autoload 'sesman-info "sesman" "\
+Display info for all current sessions (`sesman-current-sessions').
+In the resulting minibuffer display linked sessions are numbered and the
+other (friendly) sessions are not. When ALL is non-nil, show info for all
+sessions.
+
+\(fn &optional ALL)" t nil)
+
+(autoload 'sesman-link-with-buffer "sesman" "\
+Ask for SESSION and link with BUFFER.
+BUFFER defaults to current buffer. On universal argument, or if BUFFER is 'ask,
+ask for buffer.
+
+\(fn &optional BUFFER SESSION)" t nil)
+
+(autoload 'sesman-link-with-directory "sesman" "\
+Ask for SESSION and link with DIR.
+DIR defaults to `default-directory'. On universal argument, or if DIR is 'ask,
+ask for directory.
+
+\(fn &optional DIR SESSION)" t nil)
+
+(autoload 'sesman-link-with-project "sesman" "\
+Ask for SESSION and link with PROJECT.
+PROJECT defaults to current project. On universal argument, or if PROJECT is
+'ask, ask for the project. SESSION defaults to the current session.
+
+\(fn &optional PROJECT SESSION)" t nil)
+
+(autoload 'sesman-link-with-least-specific "sesman" "\
+Ask for SESSION and link with the least specific context available.
+Normally the least specific context is the project. If not in a project, link
+with the `default-directory'. If `default-directory' is nil, link with current
+buffer.
+
+\(fn &optional SESSION)" t nil)
+
+(autoload 'sesman-unlink "sesman" "\
+Break any of the previously created links.
+
+\(fn)" t nil)
+ (autoload 'sesman-map "sesman" "Session management prefix keymap." t 'keymap)
+
+;;;***
+\f
+;;;### (autoloads nil "sesman-browser" "sesman-browser.el" (23997
+;;;;;;  31641 489204 100000))
+;;; Generated autoloads from sesman-browser.el
+
+(autoload 'sesman-browser "sesman-browser" "\
+Display an interactive session browser.
+See `sesman-browser-mode' for more details.
+
+\(fn)" t nil)
+
+;;;***
+\f
+;;;### (autoloads nil nil ("sesman-pkg.el") (23997 31641 487487 99000))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+;;; sesman-autoloads.el ends here
diff --git a/elpa/sesman-20190909.1754/sesman-browser.el b/elpa/sesman-20190909.1754/sesman-browser.el
new file mode 100644 (file)
index 0000000..6f6c8cc
--- /dev/null
@@ -0,0 +1,482 @@
+;;; sesman-browser.el --- Interactive Browser for Sesman -*- lexical-binding: t -*-
+;;
+;; Copyright (C) 2018, Vitalie Spinu
+;; Author: Vitalie Spinu
+;; URL: https://github.com/vspinu/sesman
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This file is *NOT* part of GNU Emacs.
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 3, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Interactive session browser.
+;;
+;;; Code:
+
+(require 'seq)
+(require 'sesman)
+
+(defgroup sesman-browser nil
+  "Browser for Sesman."
+  :prefix "sesman-browser-"
+  :group 'sesman
+  :link '(url-link :tag "GitHub" "https://github.com/vspinu/sesman"))
+
+(defface sesman-browser-highligh-face
+  '((default (:inherit highlight :weight bold)))
+  "Face used to highlight currently selected button."
+  :group 'sesman-browser)
+
+(defface sesman-browser-button-face
+  '((default (:inherit button :slant italic)))
+  "Face used to highlight currently selected object."
+  :group 'sesman-browser)
+
+(defvar-local sesman-browser--sort-types '(name relevance))
+(defcustom sesman-browser-sort-type 'name
+  "Default sorting type in sesman browser buffers.
+Currently can be either 'name  or 'relevance."
+  :type '(choice (const name) (const relevance))
+  :group 'sesman-browser)
+
+(defvar sesman-browser-map
+  (let (sesman-browser-map)
+    (define-prefix-command 'sesman-browser-map)
+    (define-key sesman-browser-map (kbd "r") #'sesman-browser-restart-session)
+    (define-key sesman-browser-map (kbd "q") #'sesman-browser-quit-session)
+    (define-key sesman-browser-map (kbd "b") #'sesman-browser-link-with-buffer)
+    (define-key sesman-browser-map (kbd "d") #'sesman-browser-link-with-directory)
+    (define-key sesman-browser-map (kbd "p") #'sesman-browser-link-with-project)
+    (define-key sesman-browser-map (kbd "u") #'sesman-browser-unlink)
+    sesman-browser-map)
+  "Prefix keymap for sesman commands from sesman browser.")
+
+(defvar sesman-browser-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map (kbd "n") #'sesman-browser-vertical-next)
+    (define-key map (kbd "p") #'sesman-browser-vertical-prev)
+    (define-key map (kbd "f") #'sesman-browser-forward)
+    (define-key map (kbd "b") #'sesman-browser-backward)
+    (define-key map [remap forward-paragraph] #'sesman-browser-session-next)
+    (define-key map [remap backward-paragraph] #'sesman-browser-session-prev)
+    (define-key map (kbd "C-M-n") #'sesman-browser-session-next)
+    (define-key map (kbd "C-M-p") #'sesman-browser-session-prev)
+    (define-key map (kbd "<tab>") #'sesman-browser-forward)
+    (define-key map (kbd "<backtab>") #'sesman-browser-backward)
+    (define-key map (kbd "<RET>") #'sesman-goto)
+    (define-key map (kbd "o") #'sesman-show)
+    (define-key map (kbd "t") #'sesman-browser-toggle-sort)
+    (define-key map (kbd "S") #'sesman-browser-toggle-sort)
+    (define-key map (kbd "l b") #'sesman-browser-link-with-buffer)
+    (define-key map (kbd "l d") #'sesman-browser-link-with-directory)
+    (define-key map (kbd "l p") #'sesman-browser-link-with-project)
+    (define-key map (kbd "u") #'sesman-browser-unlink)
+    (define-key map (kbd "s") 'sesman-browser-map)
+    (define-key map (kbd "C-c C-s") 'sesman-browser-map)
+    (easy-menu-define sesman-browser-mode-map map
+      "Sesman Browser"
+      '("SesmanBrowser"
+        ["Next row" sesman-browser-vertical-next]
+        ["Previous row" sesman-browser-vertical-prev]
+        ["Next button" sesman-browser-forward]
+        ["Previous button" sesman-browser-backward]
+        ["Next session" sesman-browser-session-next]
+        ["Previous session" sesman-browser-session-prev]
+        "--"
+        ["Goto buffer" sesman-goto]
+        ["Show buffer" sesman-show]
+        "--"
+        ["Link with Buffer" sesman-browser-link-with-buffer]
+        ["Link with Directory" sesman-browser-link-with-directory]
+        ["Link with Project" sesman-browser-link-with-project]
+        ["Unlink" sesman-browser-unlink]
+        "--"
+        ["Toggle sort" sesman-browser-toggle-sort]
+        ["Refresh View" revert-buffer]))
+    map)
+  "Local keymap in `sesman-browser-mode'.")
+
+\f
+;;; Utilities
+
+(defun sesman-browser--closeby-pos (prop lax)
+  (or (when (get-text-property (point) prop)
+        (point))
+      (when (and (not (bobp))
+                 (get-text-property (1- (point)) prop))
+        (1- (point)))
+      (when lax
+        (let ((next (save-excursion
+                      (and
+                       (goto-char (next-single-char-property-change (point) prop))
+                       (get-text-property (point) prop)
+                       (point))))
+              (prev (save-excursion
+                      (and
+                       (goto-char (previous-single-char-property-change (point) prop))
+                       (not (bobp))
+                       (get-text-property (1- (point)) prop)
+                       (1- (point))))))
+          (if next
+              (if prev
+                  (if (< (- (point) prev) (- next (point)))
+                      prev
+                    next)
+                next)
+            prev)))))
+
+(defun sesman-browser--closeby-value (prop lax)
+  (when-let ((pos (sesman-browser--closeby-pos prop lax)))
+    (get-text-property pos prop)))
+
+(defun sesman-browser-get (what &optional no-error lax)
+  "Get value of the property WHAT at point.
+If NO-ERROR is non-nil, don't throw an error if no value has been found and
+return nil. If LAX is non-nil, search nearby and return the closest value."
+  (when (derived-mode-p 'sesman-browser-mode)
+    (or (let ((prop (pcase what
+                      ('session :sesman-session)
+                      ('link    :sesman-link)
+                      ('object  :sesman-object)
+                      (_        what))))
+          (sesman-browser--closeby-value prop 'lax))
+        (unless no-error
+          (user-error "No %s %s" what (if lax "nearby" "at point"))))))
+
+\f
+;;; Navigation
+
+(defvar-local sesman-browser--section-overlay nil)
+(defvar-local sesman-browser--stop-overlay nil)
+
+(when (fboundp 'define-fringe-bitmap)
+  (define-fringe-bitmap 'sesman-left-bar
+    [#b00001100] nil nil '(top t)))
+
+(defun sesman-browser--next (prop)
+  (let ((pos (point)))
+    (goto-char (previous-single-char-property-change (point) prop))
+    (unless (get-text-property (point) prop)
+      (goto-char (previous-single-char-property-change (point) prop)))
+    (when (bobp)
+      (goto-char pos))))
+
+(defun sesman-browser--prev (prop)
+  (let ((pos (point)))
+    (goto-char (next-single-char-property-change (point) prop))
+    (unless (get-text-property (point) prop)
+      (goto-char (next-single-char-property-change (point) prop)))
+    (when (eobp)
+      (goto-char pos))))
+
+(defun sesman-browser-forward ()
+  "Go to next button."
+  (interactive)
+  (sesman-browser--prev :sesman-stop))
+
+(defun sesman-browser-backward ()
+  "Go to previous button."
+  (interactive)
+  (sesman-browser--next :sesman-stop))
+
+(defun sesman-browser-vertical-next ()
+  "Go to next button section or row."
+  (interactive)
+  (sesman-browser--prev :sesman-vertical-stop))
+
+(defun sesman-browser-vertical-prev ()
+  "Go to previous button section or row."
+  (interactive)
+  (sesman-browser--next :sesman-vertical-stop))
+
+(defun sesman-browser-session-next ()
+  "Go to next session."
+  (interactive)
+  (sesman-browser--prev :sesman-session-stop))
+
+(defun sesman-browser-session-prev ()
+  "Go to previous session."
+  (interactive)
+  (sesman-browser--next :sesman-session-stop))
+
+\f
+;;; Display
+
+(defun sesman-goto (&optional no-switch)
+  "Go to most relevant buffer for session at point.
+If NO-SWITCH is non-nil, only display the buffer."
+  (interactive "P")
+  (let ((object (get-text-property (point) :sesman-object)))
+    (if (and object (bufferp object))
+        (if no-switch
+            (display-buffer object)
+          (pop-to-buffer object))
+      (let* ((session (sesman-browser-get 'session))
+             (info (sesman-session-info (sesman--system) session))
+             (buffers (or (plist-get info :buffers)
+                          (let ((objects (plist-get info :objects)))
+                            (seq-filter #'bufferp objects)))))
+        (if buffers
+            (let ((most-recent-buf (seq-find (lambda (b)
+                                               (member b buffers))
+                                             (buffer-list))))
+              (if no-switch
+                  (display-buffer most-recent-buf)
+                (pop-to-buffer most-recent-buf)))
+          (user-error "Cannot jump to session %s; it doesn't contain any buffers" (car session)))))))
+
+(defun sesman-show ()
+  "Show the most relevant buffer for the session at point."
+  (interactive)
+  (sesman-goto 'no-switch))
+
+(defun sesman-browser--sensor-function (&rest _ignore)
+  (let ((beg (or (when (get-text-property (point) :sesman-stop)
+                   (if (get-text-property (1- (point)) :sesman-stop)
+                       (previous-single-char-property-change (point) :sesman-stop)
+                     (point)))
+                 (next-single-char-property-change (point) :sesman-stop)))
+        (end (next-single-char-property-change (point) :sesman-stop)))
+    (move-overlay sesman-browser--stop-overlay beg end)
+    (when window-system
+      (let ((beg (get-text-property (point) :sesman-fragment-beg))
+            (end (get-text-property (point) :sesman-fragment-end)))
+        (when (and beg end)
+          (move-overlay sesman-browser--section-overlay beg end))))))
+
+\f
+;;; Sesman UI
+
+(defun sesman-browser-quit-session ()
+  "Quite session at point."
+  (interactive)
+  (sesman-quit (sesman-browser-get 'session)))
+
+(defun sesman-browser-restart-session ()
+  "Restart session at point."
+  (interactive)
+  (sesman-restart (sesman-browser-get 'session)))
+
+(defun sesman-browser-link-with-buffer ()
+  "Ask for buffer to link session at point to."
+  (interactive)
+  (let ((session (sesman-browser-get 'session)))
+    (sesman-link-with-buffer 'ask session)))
+
+(defun sesman-browser-link-with-directory ()
+  "Ask for directory to link session at point to."
+  (interactive)
+  (let ((session (sesman-browser-get 'session)))
+    (sesman-link-with-directory 'ask session)))
+
+(defun sesman-browser-link-with-project ()
+  "Ask for project to link session at point to."
+  (interactive)
+  (let ((session (sesman-browser-get 'session)))
+    (sesman-link-with-project 'ask session)))
+
+(defun sesman-browser-unlink ()
+  "Unlink the link at point or ask for link to unlink."
+  (interactive)
+  (if-let ((link (sesman-browser-get 'link 'no-error)))
+      (sesman--unlink link)
+    (if-let ((links (sesman-links (sesman--system)
+                                  (sesman-browser-get 'session))))
+        (mapc #'sesman--unlink
+              (sesman--ask-for-link "Unlink: " links 'ask-all))
+      (user-error "No links for session %s" (car (sesman-browser-get 'session)))))
+  (run-hooks 'sesman-post-command-hook))
+
+\f
+;;; Major Mode
+
+(defun sesman-browser-revert (&rest _ignore)
+  "Refresh current browser buffer."
+  (let ((pos (point)))
+    (sesman-browser)
+    ;; simple but not particularly reliable or useful
+    (goto-char (min pos (point-max)))))
+
+(defun sesman-browser-revert-all (system)
+  "Refresh all Sesman SYSTEM browsers."
+  (mapc (lambda (b)
+          (with-current-buffer b
+            (when (and (derived-mode-p 'sesman-browser-mode)
+                       (eq system (sesman--system)))
+              (sesman-browser-revert))))
+        (buffer-list)))
+
+(defun sesman-browser--goto-stop (stop-value)
+  (let ((search t))
+    (goto-char (point-min))
+    (while search
+      (goto-char (next-single-char-property-change (point) :sesman-stop))
+      (if (eobp)
+          (progn (setq search nil)
+                 (goto-char (next-single-char-property-change (point-min) :sesman-stop)))
+        (when (equal (get-text-property (point) :sesman-stop) stop-value)
+          (setq search nil))))))
+
+(defun sesman-browser-toggle-sort ()
+  "Toggle sorting of sessions.
+See `sesman-browser-sort-type' for the default sorting type."
+  (interactive)
+  (when (eq sesman-browser-sort-type
+            (car sesman-browser--sort-types))
+    (pop sesman-browser--sort-types))
+  (unless sesman-browser--sort-types
+    (setq-local sesman-browser--sort-types (default-value 'sesman-browser--sort-types)))
+  (setq sesman-browser-sort-type (pop sesman-browser--sort-types))
+  (let ((stop (sesman-browser-get :sesman-stop nil 'lax)))
+    (sesman-browser)
+    (sesman-browser--goto-stop stop)
+    (sesman-browser--sensor-function))
+  (message "Sorted by %s"
+           (propertize (symbol-name sesman-browser-sort-type) 'face 'bold)))
+
+(define-derived-mode sesman-browser-mode special-mode "SesmanBrowser"
+  "Interactive view of Sesman sessions.
+When applicable, system specific commands are locally bound to j when point is
+on a session object."
+  ;; ensure there is a sesman-system here
+  (sesman--system)
+  (delete-all-overlays)
+  (setq-local sesman-browser--stop-overlay (make-overlay (point) (point)))
+  (overlay-put sesman-browser--stop-overlay 'face 'sesman-browser-highligh-face)
+  (setq-local sesman-browser--section-overlay (make-overlay (point) (point)))
+  (when window-system
+    (let* ((fringe-spec '(left-fringe sesman-left-bar sesman-browser-highligh-face))
+           (dummy-string (propertize "|" 'display fringe-spec)))
+      (overlay-put sesman-browser--section-overlay 'line-prefix dummy-string)))
+  (add-hook 'sesman-post-command-hook 'sesman-browser-revert nil t)
+  (setq-local display-buffer-base-action '(nil . ((inhibit-same-window . t))))
+  (setq-local sesman-browser--sort-types (default-value 'sesman-browser--sort-types))
+  (setq-local revert-buffer-function #'sesman-browser-revert))
+
+(defun sesman-browser--insert-session (system ses i)
+  (let ((ses-name (car ses))
+        (head-template "%17s")
+        beg end)
+    (setq beg (point))
+
+    ;; session header
+    (insert (format "%3d: " i))
+    (insert (propertize (car ses)
+                        :sesman-stop ses-name
+                        :sesman-vertical-stop t
+                        :sesman-session-stop t
+                        'face 'bold
+                        'cursor-sensor-functions (list #'sesman-browser--sensor-function)
+                        'mouse-face 'highlight)
+            "\n")
+
+    ;; links
+    (insert (format head-template "linked-to: "))
+    (let ((link-groups (sesman-grouped-links system ses))
+          (vert-stop))
+      (dolist (grp link-groups)
+        (let* ((type (car grp)))
+          (dolist (link (cdr grp))
+            (when (> (current-column) fill-column)
+              (insert "\n" (format head-template " "))
+              (setq vert-stop nil))
+            (let ((val (sesman--abbrev-path-maybe (sesman--lnk-value link))))
+              (insert (propertize (sesman--format-context type val 'sesman-browser-button-face)
+                                  :sesman-stop (car link)
+                                  :sesman-vertical-stop (unless vert-stop (setq vert-stop t))
+                                  :sesman-link link
+                                  'cursor-sensor-functions (list #'sesman-browser--sensor-function)
+                                  'mouse-face 'highlight)))
+            (insert "  ")))))
+    (insert "\n")
+
+    ;; objects
+    (insert (format head-template "objects: "))
+    (let* ((info (sesman-session-info system ses))
+           (map (plist-get info :map))
+           (objects (plist-get info :objects))
+           (strings (or (plist-get info :strings)
+                        (mapcar (lambda (x) (format "%s" x)) objects)))
+           (kvals (seq-mapn #'cons objects strings))
+           (kvals (seq-sort (lambda (a b) (string-lessp (cdr a) (cdr b)))
+                            kvals))
+           (vert-stop))
+      (dolist (kv kvals)
+        (when (> (current-column) fill-column)
+          (insert "\n" (format head-template " "))
+          (setq vert-stop nil))
+        (let ((str (replace-regexp-in-string ses-name "%s" (cdr kv) nil t)))
+          (insert (propertize str
+                              :sesman-stop str
+                              :sesman-vertical-stop (unless vert-stop (setq vert-stop t))
+                              :sesman-object (car kv)
+                              'cursor-sensor-functions (list #'sesman-browser--sensor-function)
+                              'face 'sesman-browser-button-face
+                              'mouse-face 'highlight
+                              'help-echo "mouse-2: visit in other window"
+                              'keymap map)
+                  "  "))))
+
+    ;; session properties
+    (setq end (point))
+    (put-text-property beg end :sesman-session ses)
+    (put-text-property beg end :sesman-session-name ses-name)
+    (put-text-property beg end :sesman-fragment-beg beg)
+    (put-text-property beg end :sesman-fragment-end end)
+    (insert "\n\n")))
+
+;;;###autoload
+(defun sesman-browser ()
+  "Display an interactive session browser.
+See `sesman-browser-mode' for more details."
+  (interactive)
+  (let* ((system (sesman--system))
+         (pop-to (called-interactively-p 'any))
+         (sessions (sesman-sessions system))
+         (cur-session (when pop-to
+                        (sesman-current-session 'CIDER)))
+         (buff (get-buffer-create (format "*sesman %s browser*" system))))
+    (with-current-buffer buff
+      (setq-local sesman-system system)
+      (sesman-browser-mode)
+      (cursor-sensor-mode 1)
+      (let ((inhibit-read-only t)
+            (sessions (pcase sesman-browser-sort-type
+                        ('name (seq-sort (lambda (a b) (string-greaterp (car b) (car a)))
+                                         sessions))
+                        ('relevance (sesman--sort-sessions system sessions))
+                        (_ (error "Invalid `sesman-browser-sort-type'"))))
+            (i 0))
+        (erase-buffer)
+        (insert "\n ")
+        (insert (propertize (format "%s Sessions:" system)
+                            'face '(bold font-lock-keyword-face)))
+        (insert "\n\n")
+        (dolist (ses sessions)
+          (setq i (1+ i))
+          (sesman-browser--insert-session system ses i))
+        (when pop-to
+          (pop-to-buffer buff)
+          (sesman-browser--goto-stop (car cur-session)))
+        (sesman-browser--sensor-function)))))
+
+(provide 'sesman-browser)
+;;; sesman-browser.el ends here
diff --git a/elpa/sesman-20190909.1754/sesman-pkg.el b/elpa/sesman-20190909.1754/sesman-pkg.el
new file mode 100644 (file)
index 0000000..5f896f3
--- /dev/null
@@ -0,0 +1,12 @@
+(define-package "sesman" "20190909.1754" "Generic Session Manager"
+  '((emacs "25"))
+  :keywords
+  '("process")
+  :authors
+  '(("Vitalie Spinu"))
+  :maintainer
+  '("Vitalie Spinu")
+  :url "https://github.com/vspinu/sesman")
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
diff --git a/elpa/sesman-20190909.1754/sesman.el b/elpa/sesman-20190909.1754/sesman.el
new file mode 100644 (file)
index 0000000..e0a16b3
--- /dev/null
@@ -0,0 +1,1003 @@
+;;; sesman.el --- Generic Session Manager -*- lexical-binding: t -*-
+;;
+;; Copyright (C) 2018, Vitalie Spinu
+;; Author: Vitalie Spinu
+;; URL: https://github.com/vspinu/sesman
+;; Keywords: process
+;; Version: 0.3.3-DEV
+;; Package-Requires: ((emacs "25"))
+;; Keywords: processes, tools, vc
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This file is *NOT* part of GNU Emacs.
+;;
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation; either version 3, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
+;; Floor, Boston, MA 02110-1301, USA.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Commentary:
+;;
+;; Sesman provides facilities for session management and interactive session
+;; association with the current contexts (project, directory, buffers etc).  See
+;; project's readme for more details.
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;;; Code:
+
+(require 'cl-generic)
+(require 'seq)
+(require 'subr-x)
+(require 'vc)
+
+(defgroup sesman nil
+  "Generic Session Manager."
+  :prefix "sesman-"
+  :group 'tools
+  :link '(url-link :tag "GitHub" "https://github.com/vspinu/sesman"))
+
+(defface sesman-project-face
+  '((default (:inherit font-lock-doc-face)))
+  "Face used to mark projects."
+  :group 'sesman)
+
+(defface sesman-directory-face
+  '((default (:inherit font-lock-type-face)))
+  "Face used to mark directories."
+  :group 'sesman)
+
+(defface sesman-buffer-face
+  '((default (:inherit font-lock-preprocessor-face)))
+  "Face used to mark buffers."
+  :group 'sesman)
+
+(defcustom sesman-use-friendly-sessions t
+  "If non-nil consider friendly sessions when looking for current sessions.
+The definition of friendly sessions is system dependent but usually means
+sessions running in dependent projects."
+  :group 'sesman
+  :type 'boolean
+  :package-version '(sesman . "0.3.2"))
+
+(defcustom sesman-follow-symlinks 'vc
+  "When non-nil, follow symlinks during the file expansion.
+When nil, don't follow symlinks. When 'vc, follow symlinks only when
+`vc-follow-symlinks' is non-nil. When t, always follow symlinks."
+  :group 'sesman
+  :type '(choice (const :tag "Comply with `vc-follow-symlinks'" vc)
+                 (const :tag "Don't follow symlinks"   nil)
+                 (const :tag "Follow symlinks"         t))
+  :package-version '(sesman . "0.3.3"))
+(put 'sesman-follow-symlinks 'safe-local-variable (lambda (x) (memq x '(vc nil t))))
+
+;; (defcustom sesman-disambiguate-by-relevance t
+;;   "If t choose most relevant session in ambiguous situations, otherwise ask.
+;; Ambiguity arises when multiple sessions are associated with current context.  By
+;; default only projects could be associated with multiple sessions.  See
+;; `sesman-single-link-contexts' in order to change that.  Relevance is decided by
+;; system's implementation, see `sesman-more-relevant-p'."
+;;   :group 'sesman
+;;   :type 'boolean)
+
+(defcustom sesman-single-link-context-types '(buffer)
+  "List of context types to which at most one session can be linked."
+  :group 'sesman
+  :type '(repeat symbol)
+  :package-version '(sesman . "0.1.0"))
+
+;; FIXME:
+;; (defcustom sesman-abbreviate-paths 2
+;;   "Abbreviate paths to that many parents.
+;; When set to nil, don't abbreviate directories."
+;;   :group 'sesman
+;;   :type '(choice number
+;;                  (const :tag "Don't abbreviate" nil)))
+
+(defvar sesman-sessions-hashmap (make-hash-table :test #'equal)
+  "Hash-table of all sesman sessions.
+Key is a cons (system-name . session-name).")
+
+(defvar sesman-links-alist nil
+  "An alist of all sesman links.
+Each element is of the form (key cxt-type cxt-value) where
+\"key\" is of the form (system-name . session-name). system-name
+and cxt-type must be symbols.")
+
+(defvar-local sesman-system nil
+  "Name of the system managed by `sesman'.
+Can be either a symbol, or a function returning a symbol.")
+(put 'sesman-system 'permanent-local 't)
+
+
+\f
+;; Internal Utilities
+
+(defun sesman--on-C-u-u-sessions (system which)
+  (cond
+   ((null which)
+    (let ((ses (sesman-current-session system)))
+      (when ses
+        (list ses))))
+   ((or (equal which '(4)) (eq which 'linked))
+    (sesman--linked-sessions system 'sort))
+   ((or (equal which '(16)) (eq which 'all) (eq which t))
+    (sesman--all-system-sessions system 'sort))
+   ;; session itself
+   ((and (listp which)
+         (or (stringp (car which))
+             (symbolp (car which))))
+    (list which))
+   ;; session name
+   ((or (stringp which)
+        (symbolp which)
+        (gethash (cons system which) sesman-sessions-hashmap)))
+   (t (error "Invalid which argument (%s)" which))))
+
+(defun sesman--cap-system-name (system)
+  (let ((name (symbol-name system)))
+    (if (string-match-p "^[[:upper:]]" name)
+        name
+      (capitalize name))))
+
+(defun sesman--least-specific-context (system)
+  (seq-some (lambda (ctype)
+              (when-let (val (sesman-context ctype system))
+                (cons ctype val)))
+            (reverse (sesman-context-types system))))
+
+(defun sesman--link-session-interactively (session cxt-type cxt-val)
+  (let ((system (sesman--system)))
+    (unless cxt-type
+      (let ((cxt (sesman--least-specific-context system)))
+        (setq cxt-type (car cxt)
+              cxt-val (cdr cxt))))
+    (let ((cxt-name (symbol-name cxt-type)))
+      (if (member cxt-type (sesman-context-types system))
+          (let ((session (or session
+                             (sesman-ask-for-session
+                              system
+                              (format "Link with %s %s: "
+                                      cxt-name (sesman--abbrev-path-maybe
+                                                (sesman-context cxt-type system)))
+                              (sesman--all-system-sessions system 'sort)
+                              'ask-new))))
+            (sesman-link-session system session cxt-type cxt-val))
+        (error (format "%s association not allowed for this system (%s)"
+                       (capitalize cxt-name)
+                       system))))))
+
+;; FIXME: incorporate `sesman-abbreviate-paths'
+(defun sesman--abbrev-path-maybe (obj)
+  (if (stringp obj)
+      (abbreviate-file-name obj)
+    obj))
+
+(defun sesman--system-in-buffer (&optional buffer)
+  (with-current-buffer (or buffer (current-buffer))
+    (if (functionp sesman-system)
+        (funcall sesman-system)
+      sesman-system)))
+
+(defun sesman--system ()
+  (if sesman-system
+      (if (functionp sesman-system)
+          (funcall sesman-system)
+        sesman-system)
+    (error "No `sesman-system' in buffer `%s'" (current-buffer))))
+
+(defun sesman--linked-sessions (system &optional sort cxt-types)
+  (let* ((system (or system (sesman--system)))
+         (cxt-types (or cxt-types (sesman-context-types system))))
+    ;; just in case some links are lingering due to user errors
+    (sesman--clear-links)
+    (delete-dups
+     (mapcar (lambda (assoc)
+               (gethash (car assoc) sesman-sessions-hashmap))
+             (sesman-current-links system nil sort cxt-types)))))
+
+(defun sesman--friendly-sessions (system &optional sort)
+  (let ((sessions (seq-filter (lambda (ses) (sesman-friendly-session-p system ses))
+                              (sesman--all-system-sessions system))))
+    (if sort
+        (sesman--sort-sessions system sessions)
+      sessions)))
+
+(defun sesman--all-system-sessions (&optional system sort)
+  "Return a list of sessions registered with SYSTEM.
+If SORT is non-nil, sort in relevance order."
+  (let ((system (or system (sesman--system)))
+        sessions)
+    (maphash
+     (lambda (k s)
+       (when (eql (car k) system)
+         (push s sessions)))
+     sesman-sessions-hashmap)
+    (if sort
+        (sesman--sort-sessions system sessions)
+      sessions)))
+
+;; FIXME: make this a macro
+(defun sesman--link-lookup-fn (&optional system ses-name cxt-type cxt-val x)
+  (let ((system (or system (caar x)))
+        (ses-name (or ses-name (cdar x)))
+        (cxt-type (or cxt-type (nth 1 x)))
+        (cxt-val (or cxt-val (nth 2 x))))
+    (lambda (el)
+      (and (or (null system) (eq (caar el) system))
+           (or (null ses-name) (equal (cdar el) ses-name))
+           (or (null cxt-type)
+               (if (listp cxt-type)
+                   (member (nth 1 el) cxt-type)
+                 (eq (nth 1 el) cxt-type)))
+           (or (null cxt-val) (equal (nth 2 el) cxt-val))))))
+
+(defun sesman--unlink (x)
+  (setq sesman-links-alist
+        (seq-remove (sesman--link-lookup-fn nil nil nil nil x)
+                    sesman-links-alist)))
+
+(defun sesman--clear-links ()
+  (setq sesman-links-alist
+        (seq-filter (lambda (x)
+                      (gethash (car x) sesman-sessions-hashmap))
+                    sesman-links-alist)))
+
+(defun sesman--format-session-objects (system session &optional sep)
+  (let ((info (sesman-session-info system session)))
+    (if (and (listp info)
+             (keywordp (car info)))
+        (let ((ses-name (car session))
+              (sep (or sep " "))
+              (strings (or (plist-get info :strings)
+                           (mapcar (lambda (x) (format "%s" x))
+                                   (plist-get info :objects)))))
+          (mapconcat (lambda (str)
+                       (replace-regexp-in-string ses-name "..." str nil t))
+                     strings sep))
+      (format "%s" info))))
+
+(defun sesman--format-session (system ses &optional prefix)
+  (format (propertize "%s%s [%s] linked-to %s" 'face 'bold)
+          (or prefix "")
+          (propertize (car ses) 'face 'bold)
+          (propertize (sesman--format-session-objects system ses ", ") 'face 'italic)
+          (sesman-grouped-links system ses t t)))
+
+(defun sesman--format-link (link)
+  (let* ((system (sesman--lnk-system-name link))
+         (session (gethash (car link) sesman-sessions-hashmap)))
+    (format "%s(%s) -> %s [%s]"
+            (sesman--lnk-context-type link)
+            (propertize (format "%s" (sesman--abbrev-path-maybe (sesman--lnk-value link)))
+                        'face 'bold)
+            (propertize (sesman--lnk-session-name link) 'face 'bold)
+            (if session
+                (sesman--format-session-objects system session)
+              "invalid"))))
+
+(defun sesman--ask-for-link (prompt links &optional ask-all)
+  (let* ((name.keys (mapcar (lambda (link)
+                              (cons (sesman--format-link link) link))
+                            links))
+         (name.keys (append name.keys
+                            (when (and ask-all (> (length name.keys) 1))
+                              '(("*all*")))))
+         (nms (mapcar #'car name.keys))
+         (sel (completing-read prompt nms nil t nil nil (car nms))))
+    (cond ((string= sel "*all*")
+           links)
+          (ask-all
+           (list (cdr (assoc sel name.keys))))
+          (t
+           (cdr (assoc sel name.keys))))))
+
+(defun sesman--sort-sessions (system sessions)
+  (seq-sort (lambda (x1 x2)
+              (sesman-more-relevant-p system x1 x2))
+            sessions))
+
+(defun sesman--sort-links (system links)
+  (seq-sort (lambda (x1 x2)
+              (sesman-more-relevant-p system
+                                      (gethash (car x1) sesman-sessions-hashmap)
+                                      (gethash (car x2) sesman-sessions-hashmap)))
+            links))
+
+;; link data structure accessors
+(defun sesman--lnk-system-name (lnk)
+  (caar lnk))
+(defun sesman--lnk-session-name (lnk)
+  (cdar lnk))
+(defun sesman--lnk-context-type (lnk)
+  (cadr lnk))
+(defun sesman--lnk-value (lnk)
+  (nth 2 lnk))
+
+\f
+;;; User Interface
+
+(defun sesman-post-command-hook nil
+  "Normal hook ran after every state-changing Sesman command.")
+
+;;;###autoload
+(defun sesman-start ()
+  "Start a Sesman session."
+  (interactive)
+  (let ((system (sesman--system)))
+    (message "Starting new %s session ..." system)
+    (prog1 (sesman-start-session system)
+      (run-hooks 'sesman-post-command-hook))))
+
+;;;###autoload
+(defun sesman-restart (&optional which)
+  "Restart sesman session.
+When WHICH is nil, restart the current session; when a single universal
+argument or 'linked, restart all linked sessions; when a double universal
+argument, t or 'all, restart all sessions. For programmatic use, WHICH can also
+be a session or a name of the session, in which case that session is restarted."
+  (interactive "P")
+  (let* ((system (sesman--system))
+         (sessions (sesman--on-C-u-u-sessions system which)))
+    (if (null sessions)
+        (message "No %s sessions found" system)
+      (with-temp-message (format "Restarting %s %s %s"  system
+                                 (if (= 1 (length sessions)) "session" "sessions")
+                                 (mapcar #'car sessions))
+        (mapc (lambda (s)
+                (sesman-restart-session system s))
+              sessions))
+      ;; restarting is not guaranteed to finish here, but what can we do?
+      (run-hooks 'sesman-post-command-hook))))
+
+;;;###autoload
+(defun sesman-quit (&optional which)
+  "Terminate a Sesman session.
+When WHICH is nil, kill only the current session; when a single universal
+argument or 'linked, kill all linked sessions; when a double universal argument,
+t or 'all, kill all sessions. For programmatic use, WHICH can also be a session
+or a name of the session, in which case that session is killed."
+  (interactive "P")
+  (let* ((system (sesman--system))
+         (sessions (sesman--on-C-u-u-sessions system which)))
+    (if (null sessions)
+        (message "No %s sessions found" system)
+      (with-temp-message (format "Killing %s %s %s"  system
+                                 (if (= 1 (length sessions)) "session" "sessions")
+                                 (mapcar #'car sessions))
+        (mapc (lambda (s)
+                (sesman-unregister system s)
+                (sesman-quit-session system s))
+              sessions))
+      (run-hooks 'sesman-post-command-hook))))
+
+;;;###autoload
+(defun sesman-info (&optional all)
+  "Display info for all current sessions (`sesman-current-sessions').
+In the resulting minibuffer display linked sessions are numbered and the
+other (friendly) sessions are not. When ALL is non-nil, show info for all
+sessions."
+  (interactive "P")
+  (let* ((system (sesman--system))
+         (i 1)
+         (sessions (if all
+                       (sesman-sessions system t)
+                     (sesman-current-sessions system)))
+         (empty-prefix (if (> (length sessions) 1) "  " "")))
+    (if sessions
+        (message (mapconcat (lambda (ses)
+                              (let ((prefix (if (sesman-relevant-session-p system ses)
+                                                (prog1 (format "%d " i)
+                                                  (setq i (1+ i)))
+                                              empty-prefix)))
+                                (sesman--format-session system ses prefix)))
+                            sessions
+                            "\n"))
+      (message "No %s%s sessions"
+               (if all "" "current ")
+               system))))
+
+;;;###autoload
+(defun sesman-link-with-buffer (&optional buffer session)
+  "Ask for SESSION and link with BUFFER.
+BUFFER defaults to current buffer. On universal argument, or if BUFFER is 'ask,
+ask for buffer."
+  (interactive "P")
+  (let ((buf (if (or (eq buffer 'ask)
+                     (equal buffer '(4)))
+                 (let ((this-system (sesman--system)))
+                   (read-buffer "Link buffer: " (current-buffer) t
+                                (lambda (buf-cons)
+                                  (equal this-system
+                                         (sesman--system-in-buffer (cdr buf-cons))))))
+               (or buffer (current-buffer)))))
+    (sesman--link-session-interactively session 'buffer buf)))
+
+;;;###autoload
+(defun sesman-link-with-directory (&optional dir session)
+  "Ask for SESSION and link with DIR.
+DIR defaults to `default-directory'. On universal argument, or if DIR is 'ask,
+ask for directory."
+  (interactive "P")
+  (let ((dir (if (or (eq dir 'ask)
+                     (equal dir '(4)))
+                 (read-directory-name "Link directory: ")
+               (or dir default-directory))))
+    (sesman--link-session-interactively session 'directory dir)))
+
+;;;###autoload
+(defun sesman-link-with-project (&optional project session)
+  "Ask for SESSION and link with PROJECT.
+PROJECT defaults to current project. On universal argument, or if PROJECT is
+'ask, ask for the project. SESSION defaults to the current session."
+  (interactive "P")
+  (let* ((system (sesman--system))
+         (project (expand-file-name
+                   (if (or (eq project 'ask)
+                           (equal project '(4)))
+                       ;; FIXME: should be a completion over all known projects for this system
+                       (read-directory-name "Project: " (sesman-project system))
+                     (or project (sesman-project system))))))
+    (sesman--link-session-interactively session 'project project)))
+
+;;;###autoload
+(defun sesman-link-with-least-specific (&optional session)
+  "Ask for SESSION and link with the least specific context available.
+Normally the least specific context is the project. If not in a project, link
+with the `default-directory'. If `default-directory' is nil, link with current
+buffer."
+  (interactive "P")
+  (sesman--link-session-interactively session nil nil))
+
+;;;###autoload
+(defun sesman-unlink ()
+  "Break any of the previously created links."
+  (interactive)
+  (let* ((system (sesman--system))
+         (links (or (sesman-current-links system)
+                    (user-error "No %s links found" system))))
+    (mapc #'sesman--unlink
+          (sesman--ask-for-link "Unlink: " links 'ask-all)))
+  (run-hooks 'sesman-post-command-hook))
+
+(declare-function sesman-browser "sesman-browser")
+;;;###autoload (autoload 'sesman-map "sesman" "Session management prefix keymap." t 'keymap)
+(defvar sesman-map
+  (let (sesman-map)
+    (define-prefix-command 'sesman-map)
+    (define-key sesman-map (kbd "C-i") #'sesman-info)
+    (define-key sesman-map (kbd   "i") #'sesman-info)
+    (define-key sesman-map (kbd "C-w") #'sesman-browser)
+    (define-key sesman-map (kbd   "w") #'sesman-browser)
+    (define-key sesman-map (kbd "C-s") #'sesman-start)
+    (define-key sesman-map (kbd   "s") #'sesman-start)
+    (define-key sesman-map (kbd "C-r") #'sesman-restart)
+    (define-key sesman-map (kbd   "r") #'sesman-restart)
+    (define-key sesman-map (kbd "C-q") #'sesman-quit)
+    (define-key sesman-map (kbd   "q") #'sesman-quit)
+    (define-key sesman-map (kbd "C-l") #'sesman-link-with-least-specific)
+    (define-key sesman-map (kbd   "l") #'sesman-link-with-least-specific)
+    (define-key sesman-map (kbd "C-b") #'sesman-link-with-buffer)
+    (define-key sesman-map (kbd   "b") #'sesman-link-with-buffer)
+    (define-key sesman-map (kbd "C-d") #'sesman-link-with-directory)
+    (define-key sesman-map (kbd   "d") #'sesman-link-with-directory)
+    (define-key sesman-map (kbd "C-p") #'sesman-link-with-project)
+    (define-key sesman-map (kbd   "p") #'sesman-link-with-project)
+    (define-key sesman-map (kbd "C-u") #'sesman-unlink)
+    (define-key sesman-map (kbd "  u") #'sesman-unlink)
+    sesman-map)
+  "Session management prefix keymap.")
+
+(defvar sesman-menu
+  '("Sesman"
+    ["Show Session Info" sesman-info]
+    "--"
+    ["Start" sesman-start]
+    ["Restart" sesman-restart :active (sesman-current-session (sesman--system))]
+    ["Quit" sesman-quit :active (sesman-current-session (sesman--system))]
+    "--"
+    ["Link with Buffer" sesman-link-with-buffer :active (sesman-current-session (sesman--system))]
+    ["Link with Directory" sesman-link-with-directory :active (sesman-current-session (sesman--system))]
+    ["Link with Project" sesman-link-with-project :active (sesman-current-session (sesman--system))]
+    ["Unlink" sesman-unlink :active (sesman-current-session (sesman--system))]
+    "--"
+    ["Browser" sesman-browser :active (sesman-current-session (sesman--system))])
+  "Sesman Menu.")
+
+(defun sesman-install-menu (map)
+  "Install `sesman-menu' into MAP."
+  (easy-menu-do-define 'sesman-menu-open
+                       map
+                       (get 'sesman-menu 'variable-documentation)
+                       sesman-menu))
+
+\f
+;;; System Generic
+
+(cl-defgeneric sesman-start-session (system)
+  "Start and return SYSTEM SESSION.")
+
+(cl-defgeneric sesman-quit-session (system session)
+  "Terminate SYSTEM SESSION.")
+
+(cl-defgeneric sesman-restart-session (system session)
+  "Restart SYSTEM SESSION.
+By default, calls `sesman-quit-session' and then
+`sesman-start-session'."
+  (let ((old-name (car session)))
+    (sesman-quit-session system session)
+    (let ((new-session (sesman-start-session system)))
+      (setcar new-session old-name))))
+
+(cl-defgeneric sesman-session-info (_system session)
+  "Return a plist with :objects key containing user \"visible\" objects.
+Optional :strings value is a list of string representations of objects. Optional
+:map key is a local keymap to place on every object in the session browser.
+Optional :buffers is a list of buffers which will be used for navigation from
+the session browser. If :buffers is missing, buffers from :objects are used
+instead."
+  (list :objects (cdr session)))
+
+(cl-defgeneric sesman-project (_system)
+  "Retrieve project root in current directory (`default-directory') for SYSTEM.
+Return a string or nil if no project has been found."
+  nil)
+
+(cl-defgeneric sesman-more-relevant-p (_system session1 session2)
+  "Return non-nil if SESSION1 should be sorted before SESSION2.
+By default, sort by session name. Systems should overwrite this method to
+provide a more meaningful ordering. If your system objects are buffers you can
+use `sesman-more-recent-p' utility in this method."
+  (not (string-greaterp (car session1) (car session2))))
+
+(cl-defgeneric sesman-friendly-session-p (_system _session)
+  "Return non-nil if SESSION is a friendly session in current context.
+The \"friendship\" is system dependent but usually means sessions running in
+dependent projects. Unless SYSTEM has defined a method for this generic, there
+are no friendly sessions."
+  nil)
+
+(cl-defgeneric sesman-context-types (_system)
+  "Return a list of context types understood by SYSTEM.
+Contexts must be sorted from most specific to least specific."
+  '(buffer directory project))
+
+\f
+;;; System API
+
+(defun sesman-session (system session-name)
+  "Retrieve SYSTEM's session with SESSION-NAME from global hash."
+  (let ((system (or system (sesman--system))))
+    (gethash (cons system session-name) sesman-sessions-hashmap)))
+
+(defun sesman-sessions (system &optional sort type cxt-types)
+  "Return a list of sessions registered with SYSTEM.
+When TYPE is either 'all or nil return all sessions registered with the SYSTEM,
+when 'linked, only linked to the current context sessions, when 'friendly - only
+friendly sessions. If SORT is non-nil, sessions are sorted in the relevance
+order with linked sessions leading the list. CXT-TYPES is a list of context
+types to consider for linked sessions."
+  (let ((system (or system (sesman--system))))
+    (cond
+     ((eq type 'linked)
+      (sesman--linked-sessions system sort cxt-types))
+     ((eq type 'friendly)
+      (sesman--friendly-sessions system sort))
+     ((memq type '(all nil))
+      (if sort
+          (delete-dups
+           (append (sesman--linked-sessions system 'sort cxt-types)
+                   (sesman--all-system-sessions system 'sort)))
+        (sesman--all-system-sessions system)))
+     (t (error "Invalid session TYPE argument %s" type)))))
+
+(defun sesman-current-sessions (system &optional cxt-types)
+  "Return a list of SYSTEM sessions active in the current context.
+Sessions are ordered by the relevance order and linked sessions come first. If
+`sesman-use-friendly-sessions' current sessions consist of linked and friendly
+sessions, otherwise only of linked sessions. CXT-TYPES is a list of context
+types to consider. Defaults to the list returned from `sesman-context-types'."
+  (if sesman-use-friendly-sessions
+      (delete-dups
+       (append (sesman--linked-sessions system 'sort cxt-types)
+               (sesman--friendly-sessions system 'sort)))
+    (sesman--linked-sessions system 'sort cxt-types)))
+
+(defun sesman-current-session (system &optional cxt-types)
+  "Get the most relevant current session for the SYSTEM.
+CXT-TYPES is a list of context types to consider."
+  (or (car (sesman--linked-sessions system 'sort cxt-types))
+      (car (sesman--friendly-sessions system 'sort))))
+
+(defun sesman-ensure-session (system &optional cxt-types)
+  "Get the most relevant linked session for SYSTEM or throw if none exists.
+CXT-TYPES is a list of context types to consider."
+  (or (sesman-current-session system cxt-types)
+      (user-error "No linked %s sessions" system)))
+
+(defun sesman-has-sessions-p (system)
+  "Return t if there is at least one session registered with SYSTEM."
+  (let ((system (or system (sesman--system)))
+        (found))
+    (condition-case nil
+        (maphash (lambda (k _)
+                   (when (eq (car k) system)
+                     (setq found t)
+                     (throw 'found nil)))
+                 sesman-sessions-hashmap)
+      (error))
+    found))
+
+(defvar sesman--select-session-history nil)
+(defun sesman-ask-for-session (system prompt &optional sessions ask-new ask-all)
+  "Ask for a SYSTEM session with PROMPT.
+SESSIONS defaults to value returned from `sesman-sessions'.  If
+ASK-NEW is non-nil, offer *new* option to start a new session.  If
+ASK-ALL is non-nil offer *all* option.  If ASK-ALL is non-nil,
+return a list of sessions, otherwise a single session."
+  (let* ((sessions (or sessions (sesman-sessions system)))
+         (name.syms (mapcar (lambda (s)
+                              (let ((name (car s)))
+                                (cons (if (symbolp name) (symbol-name name) name)
+                                      name)))
+                            sessions))
+         (nr (length name.syms))
+         (syms (if (and (not ask-new) (= nr 0))
+                   (error "No %s sessions found" system)
+                 (append name.syms
+                         (when ask-new '(("*new*")))
+                         (when (and ask-all (> nr 1))
+                           '(("*all*"))))))
+         (def (caar syms))
+         ;; (def (if (assoc (car sesman--select-session-history) syms)
+         ;;          (car sesman--select-session-history)
+         ;;        (caar syms)))
+         (sel (completing-read
+               prompt (mapcar #'car syms) nil t nil 'sesman--select-session-history def)))
+    (cond
+     ((string= sel "*new*")
+      (let ((ses (sesman-start-session system)))
+        (message "Started %s" (car ses))
+        (if ask-all (list ses) ses)))
+     ((string= sel "*all*")
+      sessions)
+     (t
+      (let* ((sym (cdr (assoc sel syms)))
+             (ses (assoc sym sessions)))
+        (if ask-all (list ses) ses))))))
+
+(defvar sesman--cxt-abbrevs '(buffer "buf" project "proj" directory "dir"))
+(defun sesman--format-context (cxt-type cxt-val extra-face)
+  (let* ((face (intern (format "sesman-%s-face" cxt-type)))
+         (short-type (propertize (or (plist-get sesman--cxt-abbrevs cxt-type)
+                                     (symbol-value cxt-type))
+                                 'face (list (if (facep face)
+                                                 face
+                                               'font-lock-function-name-face)
+                                             extra-face))))
+    (concat short-type
+            (propertize (format "(%s)" cxt-val)
+                        'face extra-face))))
+
+(defun sesman-grouped-links (system session &optional current-first as-string)
+  "Retrieve all links for SYSTEM's SESSION from the global `sesman-links-alist'.
+Return an alist of the form
+
+   ((buffer buffers..)
+    (directory directories...)
+    (project projects...)).
+
+When `CURRENT-FIRST' is non-nil, a cons of two lists as above is returned with
+car containing links relevant in current context and cdr all other links. If
+AS-STRING is non-nil, return an equivalent string representation."
+  (let* ((system (or system (sesman--system)))
+         (session (or session (sesman-current-session system)))
+         (ses-name (car session))
+         (links (thread-last sesman-links-alist
+                  (seq-filter (sesman--link-lookup-fn system ses-name))
+                  (sesman--sort-links system)
+                  (reverse)))
+         (out (mapcar (lambda (x) (list x))
+                      (sesman-context-types system)))
+         (out-rel (when current-first
+                    (copy-alist out))))
+    (mapc (lambda (link)
+            (let* ((type (sesman--lnk-context-type link))
+                   (entry (if (and current-first
+                                   (sesman-relevant-link-p link))
+                              (assoc type out-rel)
+                            (assoc type out))))
+              (when entry
+                (setcdr entry (cons link (cdr entry))))))
+          links)
+    (let ((out (delq nil (mapcar (lambda (el) (and (cdr el) el)) out)))
+          (out-rel (delq nil (mapcar (lambda (el) (and (cdr el) el)) out-rel))))
+      (if as-string
+          (let ((fmt-fn (lambda (typed-links)
+                          (let* ((type (car typed-links)))
+                            (mapconcat (lambda (lnk)
+                                         (let ((val (sesman--abbrev-path-maybe
+                                                     (sesman--lnk-value lnk))))
+                                           (sesman--format-context type val 'italic)))
+                                       (cdr typed-links)
+                                       ", ")))))
+            (if out-rel
+                (concat (mapconcat fmt-fn out-rel ", ")
+                        (when out " | ")
+                        (mapconcat fmt-fn out ", "))
+              (mapconcat fmt-fn out ", ")))
+        (if current-first
+            (cons out-rel out)
+          out)))))
+
+(defun sesman-link-session (system session &optional cxt-type cxt-val)
+  "Link SYSTEM's SESSION to context give by CXT-TYPE and CXT-VAL.
+If CXT-TYPE is nil, use the least specific type available in the current
+context. If CXT-TYPE is non-nil, and CXT-VAL is not given, retrieve it with
+`sesman-context'. See also `sesman-link-with-project',
+`sesman-link-with-directory' and `sesman-link-with-buffer'."
+  (let* ((ses-name (or (car-safe session)
+                       (error "SESSION must be a headed list")))
+         (cxt-val (or cxt-val
+                      (or (if cxt-type
+                              (sesman-context cxt-type system)
+                            (let ((cxt (sesman--least-specific-context system)))
+                              (setq cxt-type (car cxt))
+                              (cdr cxt)))
+                          (error "No local context of type %s" cxt-type))))
+         (cxt-val (if (stringp cxt-val)
+                      (expand-file-name cxt-val)
+                    cxt-val))
+         (key (cons system ses-name))
+         (link (list key cxt-type cxt-val)))
+    (if (member cxt-type sesman-single-link-context-types)
+        (thread-last sesman-links-alist
+          (seq-remove (sesman--link-lookup-fn system nil cxt-type cxt-val))
+          (cons link)
+          (setq sesman-links-alist))
+      (unless (seq-filter (sesman--link-lookup-fn system ses-name cxt-type cxt-val)
+                          sesman-links-alist)
+        (setq sesman-links-alist (cons link sesman-links-alist))))
+    (run-hooks 'sesman-post-command-hook)
+    link))
+
+(defun sesman-links (system &optional session-or-name cxt-types sort)
+  "Retrieve all links for SYSTEM, SESSION-OR-NAME and CXT-TYPES.
+SESSION-OR-NAME can be either a session or a name of the session. If SORT is
+non-nil links are sorted in relevance order and `sesman-current-links' lead the
+list, otherwise links are returned in the creation order."
+  (let* ((ses-name (if (listp session-or-name)
+                       (car session-or-name)
+                     session-or-name))
+         (lfn (sesman--link-lookup-fn system ses-name cxt-types)))
+    (if sort
+        (delete-dups (append
+                      (sesman-current-links system ses-name)
+                      (sesman--sort-links system (seq-filter lfn sesman-links-alist))))
+      (seq-filter lfn sesman-links-alist))))
+
+(defun sesman-current-links (system &optional session-or-name sort cxt-types)
+  "Retrieve all active links in current context for SYSTEM and SESSION-OR-NAME.
+SESSION-OR-NAME can be either a session or a name of the session. CXT-TYPES is a
+list of context types to consider. Returned links are a subset of
+`sesman-links-alist' sorted in order of relevance if SORT is non-nil."
+  ;; mapcan is a built-in in 26.1; don't want to require cl-lib for one function
+  (let ((ses-name (if (listp session-or-name)
+                      (car session-or-name)
+                    session-or-name)))
+    (seq-mapcat
+     (lambda (cxt-type)
+       (let* ((lfn (sesman--link-lookup-fn system ses-name cxt-type))
+              (links (seq-filter (lambda (l)
+                                   (and (funcall lfn l)
+                                        (sesman-relevant-context-p cxt-type (sesman--lnk-value l))))
+                                 sesman-links-alist)))
+         (if sort
+             (sesman--sort-links system links)
+           links)))
+     (or cxt-types (sesman-context-types system)))))
+
+(defun sesman-has-links-p (system &optional cxt-types)
+  "Return t if there is at least one linked session.
+CXT-TYPES defaults to `sesman-context-types' for current SYSTEM."
+  (let ((cxt-types (or cxt-types (sesman-context-types system)))
+        (found))
+    (condition-case nil
+        (mapc (lambda (l)
+                (when (eq system (sesman--lnk-system-name l))
+                  (let ((cxt (sesman--lnk-context-type l)))
+                    (when (and (member cxt cxt-types)
+                               (sesman-relevant-context-p cxt (sesman--lnk-value l)))
+                      (setq found t)
+                      (throw 'found nil)))))
+              sesman-links-alist)
+      (error))
+    found))
+
+(defun sesman-register (system session)
+  "Register SESSION into `sesman-sessions-hashmap' and `sesman-links-alist'.
+SYSTEM defaults to current system.  If a session with same name is already
+registered in `sesman-sessions-hashmap', change the name by appending \"#1\",
+\"#2\" ... to the name.  This function should be called by system-specific
+connection initializers (\"run-xyz\", \"xyz-jack-in\" etc.)."
+  (let* ((system (or system (sesman--system)))
+         (ses-name (car session))
+         (ses-name0 (car session))
+         (i 1))
+    (while (sesman-session system ses-name)
+      (setq ses-name (format "%s#%d" ses-name0 i)
+            i (1+ i)))
+    (setq session (cons ses-name (cdr session)))
+    (puthash (cons system ses-name) session sesman-sessions-hashmap)
+    (sesman-link-session system session)
+    session))
+
+(defun sesman-unregister (system session)
+  "Unregister SESSION.
+SYSTEM defaults to current system.  Remove session from
+`sesman-sessions-hashmap' and `sesman-links-alist'."
+  (let ((ses-key (cons system (car session))))
+    (remhash ses-key sesman-sessions-hashmap)
+    (sesman--clear-links)
+    session))
+
+(defun sesman-add-object (system session-name object &optional allow-new)
+  "Add (destructively) OBJECT to session SESSION-NAME of SYSTEM.
+If ALLOW-NEW is nil and session with SESSION-NAME does not exist
+throw an error, otherwise register a new session with
+session (list SESSION-NAME OBJECT)."
+  (let* ((system (or system (sesman--system)))
+         (session (sesman-session system session-name)))
+    (if session
+        (setcdr session (cons object (cdr session)))
+      (if allow-new
+          (sesman-register system (list session-name object))
+        (error "%s session '%s' does not exist"
+               (sesman--cap-system-name system) session-name)))))
+
+(defun sesman-remove-object (system session-name object &optional auto-unregister no-error)
+  "Remove (destructively) OBJECT from session SESSION-NAME of SYSTEM.
+If SESSION-NAME is nil, retrieve the session with
+`sesman-session-for-object'.  If OBJECT is the last object in sesman
+session, `sesman-unregister' the session.  If AUTO-UNREGISTER is non-nil
+unregister sessions of length 0 and remove all the links with the session.
+If NO-ERROR is non-nil, don't throw an error if OBJECT is not found in any
+session.  This is useful if there are several \"concurrent\" parties which
+can remove the object."
+  (let* ((system (or system (sesman--system)))
+         (session (if session-name
+                      (sesman-session system session-name)
+                    (sesman-session-for-object system object no-error)))
+         (new-session (delete object session)))
+    (cond ((null new-session))
+          ((= (length new-session) 1)
+           (when auto-unregister
+             (sesman-unregister system session)))
+          (t
+           (puthash (cons system (car session)) new-session sesman-sessions-hashmap)))))
+
+(defun sesman-session-for-object (system object &optional no-error)
+  "Retrieve SYSTEM session which contains OBJECT.
+When NO-ERROR is non-nil, don't throw an error if OBJECT is not part of any
+session.  In such case, return nil."
+  (let* ((system (or system (sesman--system)))
+         (sessions (sesman--all-system-sessions system)))
+    (or (seq-find (lambda (ses)
+                    (seq-find (lambda (x) (equal object x)) (cdr ses)))
+                  sessions)
+        (unless no-error
+          (error "%s is not part of any %s sessions"
+                 object system)))))
+
+(defun sesman-session-name-for-object (system object &optional no-error)
+  "Retrieve the name of the SYSTEM's session containing OBJECT.
+When NO-ERROR is non-nil, don't throw an error if OBJCECT is not part of
+any session.  In such case, return nil."
+  (car (sesman-session-for-object system object no-error)))
+
+(defun sesman-more-recent-p (bufs1 bufs2)
+  "Return t if BUFS1 is more recent than BUFS2.
+BUFS1 and BUFS2 are either buffers or lists of buffers.  When lists of
+buffers, most recent buffers from each list are considered.  To be used
+primarily in `sesman-more-relevant-p' methods when session objects are
+buffers."
+  (let ((bufs1 (if (bufferp bufs1) (list bufs1) bufs1))
+        (bufs2 (if (bufferp bufs2) (list bufs2) bufs2)))
+    (eq 1 (seq-some (lambda (b)
+                      (if (member b bufs1)
+                          1
+                        (when (member b bufs2)
+                          -1)))
+                    (buffer-list)))))
+
+;; path caching because file-truename is very slow
+(defvar sesman--path-cache (make-hash-table :test #'equal))
+(defun sesman-expand-path (path)
+  "Expand PATH with optionally follow symlinks.
+Whether symlinks are followed is controlled by `sesman-follow-symlinks' custom
+variable. Always return the expansion without the trailing directory slash."
+  (directory-file-name
+   (if sesman-follow-symlinks
+       (let ((true-name (or (gethash path sesman--path-cache)
+                            (puthash path (file-truename path) sesman--path-cache))))
+         (if (or (eq sesman-follow-symlinks t)
+                 vc-follow-symlinks)
+             true-name
+           ;; sesman-follow-symlinks is 'vc but vc-follow-symlinks is nil
+           (expand-file-name path)))
+     (expand-file-name path))))
+
+\f
+;;; Contexts
+
+(cl-defgeneric sesman-context (_cxt-type _system)
+  "Given SYSTEM and context type CXT-TYPE return the context.")
+(cl-defmethod sesman-context ((_cxt-type (eql buffer)) _system)
+  "Return current buffer."
+  (current-buffer))
+(cl-defmethod sesman-context ((_cxt-type (eql directory)) _system)
+  "Return current directory."
+  (sesman-expand-path default-directory))
+(cl-defmethod sesman-context ((_cxt-type (eql project)) system)
+  "Return current project."
+  (let* ((default-directory (sesman-expand-path default-directory))
+         (proj (or
+                (sesman-project (or system (sesman--system)))
+                ;; Normally we would use (project-roots (project-current)) but currently
+                ;; project-roots fails on nil and doesn't work on custom `('foo .
+                ;; "path/to/project"). So, use vc as a fallback and don't use project.el at
+                ;; all for now.
+                ;; NB: `vc-root-dir' doesn't work from symlinked files. Emacs Bug?
+                (vc-root-dir))))
+    (when proj
+      (expand-file-name proj))))
+
+(cl-defgeneric sesman-relevant-context-p (_cxt-type cxt)
+  "Non-nil if context CXT is relevant to current context of type CXT-TYPE.")
+(cl-defmethod sesman-relevant-context-p ((_cxt-type (eql buffer)) buf)
+  "Non-nil if BUF is `current-buffer'."
+  (eq (current-buffer) buf))
+(cl-defmethod sesman-relevant-context-p ((_cxt-type (eql directory)) dir)
+  "Non-nil if DIR is the parent or equals the `default-directory'."
+  (when (and dir default-directory)
+    (string-match-p (concat "^" (sesman-expand-path dir))
+                    (sesman-expand-path default-directory))))
+(cl-defmethod sesman-relevant-context-p ((_cxt-type (eql project)) proj)
+  "Non-nil if PROJ is the parent or equal to the `default-directory'."
+  (when (and proj default-directory)
+    (string-match-p (concat "^" (sesman-expand-path proj))
+                    (sesman-expand-path default-directory))))
+
+(defun sesman-relevant-link-p (link &optional cxt-types)
+  "Return non-nil if LINK is relevant to the current context.
+If CXT-TYPES is non-nil, only check relevance for those contexts."
+  (when (or (null cxt-types)
+            (member (sesman--lnk-context-type link) cxt-types))
+    (sesman-relevant-context-p
+     (sesman--lnk-context-type link)
+     (sesman--lnk-value link))))
+
+(defun sesman-relevant-session-p (system session &optional cxt-types)
+  "Return non-nil if SYSTEM's SESSION is relevant to the current context.
+If CXT-TYPES is non-nil, only check relevance for those contexts."
+  (seq-some #'sesman-relevant-link-p
+            (sesman-links system session cxt-types)))
+
+(define-obsolete-function-alias 'sesman-linked-sessions 'sesman--linked-sessions "v0.3.2")
+
+(provide 'sesman)
+
+;;; sesman.el ends here
diff --git a/elpa/sesman-readme.txt b/elpa/sesman-readme.txt
new file mode 100644 (file)
index 0000000..653b895
--- /dev/null
@@ -0,0 +1,3 @@
+Sesman provides facilities for session management and interactive session
+association with the current contexts (project, directory, buffers etc).  See
+project's readme for more details.
diff --git a/elpa/xml+-20170727.2351/xml+-autoloads.el b/elpa/xml+-20170727.2351/xml+-autoloads.el
new file mode 100644 (file)
index 0000000..224b5ce
--- /dev/null
@@ -0,0 +1,15 @@
+;;; xml+-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
+\f
+;;;### (autoloads nil nil ("xml+.el") (23997 31593 860347 792000))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; End:
+;;; xml+-autoloads.el ends here
diff --git a/elpa/xml+-20170727.2351/xml+-pkg.el b/elpa/xml+-20170727.2351/xml+-pkg.el
new file mode 100644 (file)
index 0000000..4f8add0
--- /dev/null
@@ -0,0 +1,2 @@
+;;; -*- no-byte-compile: t -*-
+(define-package "xml+" "20170727.2351" "Utilities for xml and html trees" '((emacs "24.4") (dash "2.12.0")) :commit "232fa863c08fc159b21dd58c39ea45dce3334895" :keywords '("xml" "html") :authors '(("Ben Dean" . "bendean837NOSPAMgmail.com")) :maintainer '("Ben Dean" . "bendean837NOSPAMgmail.com") :url "https://github.com/bddean/xml-plus")
diff --git a/elpa/xml+-20170727.2351/xml+.el b/elpa/xml+-20170727.2351/xml+.el
new file mode 100644 (file)
index 0000000..e090df8
--- /dev/null
@@ -0,0 +1,147 @@
+;;; xml+.el --- Utilities for xml and html trees
+
+;; Author: Ben Dean <bendean837NOSPAMgmail.com>
+;; Version: 0.0.0
+;; Package-Version: 20170727.2351
+;; Package-Requires: ((emacs "24.4") (dash "2.12.0"))
+;; Keywords: xml, html
+;; URL: https://github.com/bddean/xml-plus
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+;;; Commentary:
+
+;; Utility functions for xml parse trees.
+;;  - `xml+-query-all' and `xml+-query-first' are query functions that search
+;;     descendants in node lists. They don't work with namespace-aware parsing yet
+;;
+;;  - `xml+-node-text' gets node text
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'dash)
+(require 'subr-x)
+(require 'xml)
+
+(defun xml+--node-matches (node matcher)
+  "Return non-nil if xml/html node NODE matches query selector
+element MATCHER, an attribute-value plist optionally beginning
+with a tag name or list of tag names, e.g. ((p div) :class
+\"content\")
+
+Begin MATCHER with ~ to negate the match
+
+If MATCHER is a list of lists, it matches node if node matches
+any of its members.
+"
+  (if (eq (type-of node) 'string)
+      nil ;; TODO text matching
+    (let ((tags nil)
+          (text nil)
+          (negative nil))
+      (setq matcher (-clone matcher))
+      (if (-every? 'listp matcher)
+          (-any? `(lambda (m) (xml+--node-matches (quote ,node) m)) matcher)
+        (when (eq (car matcher) '~)
+          (setq negative t)
+          (setq matcher (cdr matcher)))
+
+        (when (and matcher
+                   (not (keywordp (cl-first matcher))))
+          (setq tags (-flatten (list (pop matcher)))))
+
+        (not (equal ;; xor
+                                                       negative
+                                                       (and
+               ;; Match tags
+                                                        (or (not tags) (memq (xml-node-name node) tags))
+               ;; Match attributes
+                                                        (let ((matches t))
+                                                                (while (and matcher matches)
+                                                                        (when (not (keywordp (car matcher)))
+                                                                                (error (format "Expected keyword in matcher, got %s"
+                                                                                                                                               (symbol-name (type-of (car matcher))))))
+                                                                        (setq matches
+                                                                                                (equal (cdr (assoc (intern (substring (symbol-name (car matcher)) 1))
+                                                                                                                                                                               (xml-node-attributes node)))
+                                                                                                                               (cadr matcher)))
+                                                                        (setq matcher (cddr matcher)))
+                                                                matches))))))))
+
+(defun xml+-query--generic (just-one nodes query &optional result must-be-root)
+       "Recursive depth first search to collect one or all nodes in
+NODES matching QUERY."
+       ;; Make cons cell to store a persistent reference to the result
+  (unless result (setq result (cons nil nil)))
+  (if (equal (car query) '>)
+      (xml+-query--generic just-one nodes (cdr query) result t)
+    (when (eq (type-of (car nodes)) 'symbol)
+      (setq nodes (list nodes)))
+
+    (let ((nodes-remaining (-filter (lambda (n) (and n (listp n))) nodes))
+          (node nil))
+
+      (while nodes-remaining
+        (setq node (pop nodes-remaining))
+        (if (xml+--node-matches node (car query))
+            (if (cdr query)
+                (xml+-query--generic just-one (xml-node-children node) (cdr query) result)
+              (setcdr result (append (cdr result) (list node)))
+              (when just-one (setq nodes-remaining nil)))
+          (unless must-be-root
+            (xml+-query--generic just-one (xml-node-children node) query result)))))
+    (reverse (cdr result))))
+
+(defun xml+-query-all (nodes query &optional must-be-root)
+       "Search NODES for matches.
+NODES is a single xml or html node or a list of them.
+
+QUERY is a list of node matchers optionally preceded by the
+symbol `>'. Node matchers are usually descendant matchers. When
+preceded by '> they are direct decendant matchers.
+
+For example, the analog to the Javascript call
+document.querySelectorAll(\"body div#post > p.content\") is:
+
+  (xml+-query-all document '((body)
+                             (div :id \"post\") >
+                             (p :class \"content\")
+                             (a)))
+
+See also `xml-node-matches'"
+       (xml+-query--generic nil nodes query must-be-root))
+
+(defun xml+-query-first (nodes query &optional must-be-root)
+       "Like `xml+-query-all', but only return the first match."
+  (car (xml+-query--generic t nodes query must-be-root)))
+
+(defun xml+-node-text (node)
+  "Get the text of NODE"
+  (string-trim
+   (replace-regexp-in-string "[\s\t\n]+" " "
+                             (mapconcat 'concat (xml+-node-text--helper node) " "))))
+
+(defun xml+-node-text--helper (node)
+  "Get the text of NODE"
+  (if (stringp node)
+      (list node)
+    (-reduce-from
+     (lambda (n1 n2) (append n1 (xml+-node-text--helper n2)))
+     nil
+     (xml-node-children node))))
+
+(provide 'xml+)
+;;; xml+.el ends here
diff --git a/elpa/xml+-readme.txt b/elpa/xml+-readme.txt
new file mode 100644 (file)
index 0000000..0ff9c57
--- /dev/null
@@ -0,0 +1,5 @@
+Utility functions for xml parse trees.
+ - `xml+-query-all' and `xml+-query-first' are query functions that search
+    descendants in node lists. They don't work with namespace-aware parsing yet
+
+ - `xml+-node-text' gets node text