From 067bd20fb168b3ae80c31ca1058cbd7e2ae2609d Mon Sep 17 00:00:00 2001 From: Andrew Danger Lyon Date: Tue, 11 Aug 2015 20:13:35 -0700 Subject: [PATCH] enable paren matchign in demo --- index.md | 1 + js/highlight-lisp/highlight-lisp.js | 98 ++++++++++++++++++++++++++ js/highlight-lisp/themes/dark.css | 46 ++++++------ js/highlight-lisp/themes/github.css | 46 ++++++------ js/highlight-lisp/themes/vestigial.css | 29 ++++---- js/highlight-lisp/themes/wookie.css | 46 ++++++------ 6 files changed, 190 insertions(+), 76 deletions(-) diff --git a/index.md b/index.md index 06c77c6..933748d 100644 --- a/index.md +++ b/index.md @@ -74,5 +74,6 @@ function switch_theme(name) { return false; } HighlightLisp.highlight_auto(); +HighlightList.paren_match(); diff --git a/js/highlight-lisp/highlight-lisp.js b/js/highlight-lisp/highlight-lisp.js index 0e1499f..436dc3d 100644 --- a/js/highlight-lisp/highlight-lisp.js +++ b/js/highlight-lisp/highlight-lisp.js @@ -379,6 +379,7 @@ var highlight_lisp = function() { */ this.highlight_element = function(code_el) { + code_el.className += ' hl-highlighted'; var html = code_el.innerHTML; // can't have &...;'s running wild like a pack of animals... html = html.replace(/&/g, '&'); @@ -393,6 +394,10 @@ var highlight_lisp = function() { } // unpad HTML string html = html.replace(/(^\n|\n$)/g, ''); + html = html.replace(/<(?!\/?span)/g, '<'); + // Re-encode stray &s to conform with XHTML + //html = html.replace(/&/g, '&'); + code_el.innerHTML = html; }, @@ -415,6 +420,99 @@ var highlight_lisp = function() { this.highlight_element(code); } } + }, + + /** + * If called, enables paren matching (hovering over a paren will add the + * "active" class to both the highlighted and the matching paren) + */ + this.paren_match = function(options) + { + options || (options = {}); + + if(!('querySelector' in document)) + { + console.error('HighlightLisp.paren_match: browser does not support querySelector/matches'); + return; + } + + var matches = function(element, selector) + { + if(!element) return; + var domatch; + var tests = ['matches', 'msMatchesSelector', 'mozMatchesSelector', 'webkitMatchesSelector']; + for(var i = 0; i < tests.length; i++) + { + if(!(tests[i] in element)) continue; + domatch = element[tests[i]]; + break; + } + + return domatch.call(element, selector); + }; + + var is_paren = function(el) + { + return matches(el, 'code > .list, code span:not(.comment):not(.string) .list'); + }; + + var find_match = function(paren) + { + // grab all non-commented/stringed parens + var children = paren.parentElement.querySelectorAll('code > span.list, code span:not(.comment):not(.string) .list'); + // turn them into a real array + children = Array.prototype.slice.call(children); + + var is_opening = function(el) { return el.innerHTML == '('; }; + + // tracks when to start counting parens + var count = false; + // tests if this is an opening or closing paren + var opening = is_opening(paren); + // if this is a closing paren, reverse the children so we can search + // backwards just by going forwards + if(!opening) children.reverse(); + + for(var i = 0; i < children.length; i++) + { + var child = children[i]; + var open = is_opening(child); + // mark the first occurance of the paren, and start counting + // from there + if(child === paren) + { + count = 1; + continue; + } + if(count === false) continue; + if(opening == open) count++; + else count--; + if(count === 0) return child; + } + }; + + var add_class = function(el, classname, add) + { + if(!el) return; + el.className = el.className.replace(new RegExp(classname, 'g'), ''); + if(add) el.className += ' '+classname; + }; + + var codes = document.getElementsByClassName('hl-highlighted'); + for(var i = 0; i < codes.length; i++) + { + var code = codes[i]; + var listener = function(add, e) + { + var hovered = e.target; + if(!is_paren(hovered)) return; + var match = find_match(hovered); + add_class(hovered, 'active', add); + add_class(match, 'active', add); + }; + code.addEventListener('mouseover', listener.bind(this, true)); + code.addEventListener('mouseout', listener.bind(this, false)); + } } }; diff --git a/js/highlight-lisp/themes/dark.css b/js/highlight-lisp/themes/dark.css index ab2464b..272a806 100644 --- a/js/highlight-lisp/themes/dark.css +++ b/js/highlight-lisp/themes/dark.css @@ -2,26 +2,30 @@ * Inspired by highlight.js's "Tomorrow night" theme */ pre { white-space: pre; background-color: #1d1f21; border: 0px solid #ccc; font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-radius: 3px; } -pre code.lisp {white-space: pre; margin: 0; padding: 0; background: none; border: none; overflow-x: auto; font-size: 13px;} -code.lisp {margin: 0 2px; padding: 0 5px; white-space: nowrap; font-family: Consolas, "Liberation Mono", Courier, monospace; background: #f8f8f8; border: 1px solid #eaeaea; border-radius: 3px;} +pre code.hl-highlighted {white-space: pre; margin: 0; padding: 0; background: none; border: none; overflow-x: auto; font-size: 13px;} +code.hl-highlighted {margin: 0 2px; padding: 0 5px; white-space: nowrap; font-family: Consolas, "Liberation Mono", Courier, monospace; background: #f8f8f8; border: 1px solid #eaeaea; border-radius: 3px;} -code.lisp {color: #c5c8c6;} -code.lisp .function {color: #abc; color: #cba;} -code.lisp .function.known {color: #81a2be; color: #91b2ce;} -code.lisp .function.known.special {color: #ba7; font-weight: bold;} -code.lisp .keyword {color: #b299ab;} -code.lisp .keyword.known {color: #b294bb;} -code.lisp .symbol {color: #c9c;} -code.lisp .lambda-list {color: #9aa;} -code.lisp .number {color: #c76;} -code.lisp .variable.known {color: #9dd;} -code.lisp .variable.global {color: #aaa;} -code.lisp .variable.constant {color: #a77;} -code.lisp .nil {color: #de935f;} -code.lisp .list {} +code.hl-highlighted {color: #c5c8c6;} +code.hl-highlighted .function {color: #abc; color: #cba;} +code.hl-highlighted .function.known {color: #81a2be; color: #91b2ce;} +code.hl-highlighted .function.known.special {color: #ba7; font-weight: bold;} +code.hl-highlighted .keyword {color: #b299ab;} +code.hl-highlighted .keyword.known {color: #b294bb;} +code.hl-highlighted .symbol {color: #c9c;} +code.hl-highlighted .lambda-list {color: #9aa;} +code.hl-highlighted .number {color: #c76;} +code.hl-highlighted .variable.known {color: #9dd;} +code.hl-highlighted .variable.global {color: #aaa;} +code.hl-highlighted .variable.constant {color: #a77;} +code.hl-highlighted .nil {color: #de935f;} +code.hl-highlighted .list {} + +code.hl-highlighted .string, code.hl-highlighted .string * {color: #b5bd88 !important;} +code.hl-highlighted .comment, +code.hl-highlighted .comment *, +code.hl-highlighted .comment .string +code.hl-highlighted .comment .string * {color: #777 !important;} +code.hl-highlighted .string .comment {color: #b5bd88 !important;} + +code.hl-highlighted .list.active {display: inline-block; color: #333; background: #aaa;} -code.lisp .string, code.lisp .string * {color: #b5bd88 !important;} -code.lisp .comment, -code.lisp .comment *, -code.lisp .comment .string -code.lisp .comment .string * {color: #777 !important;} diff --git a/js/highlight-lisp/themes/github.css b/js/highlight-lisp/themes/github.css index 8031c64..e21fcab 100644 --- a/js/highlight-lisp/themes/github.css +++ b/js/highlight-lisp/themes/github.css @@ -2,26 +2,30 @@ * Inspired by github's default code highlighting */ pre { white-space: pre; background-color: #f8f8f8; border: 1px solid #ccc; font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-radius: 3px; } -pre code.lisp {white-space: pre; margin: 0; padding: 0; background: none; border: none; overflow-x: auto; font-size: 13px;} -code.lisp {margin: 0 2px; padding: 0 5px; white-space: nowrap; font-family: Consolas, "Liberation Mono", Courier, monospace; background: #f8f8f8; border: 1px solid #eaeaea; border-radius: 3px;} +pre code.hl-highlighted {white-space: pre; margin: 0; padding: 0; background: none; border: none; overflow-x: auto; font-size: 13px;} +code.hl-highlighted {margin: 0 2px; padding: 0 5px; white-space: nowrap; font-family: Consolas, "Liberation Mono", Courier, monospace; background: #f8f8f8; border: 1px solid #eaeaea; border-radius: 3px;} -code.lisp {color: #008080;} -code.lisp .function {color: #008080;} -code.lisp .function.known {color: #800603;} -code.lisp .function.known.special {color: #2d2d2d; font-weight: bold;} -code.lisp .keyword {color: #990073;} -code.lisp .keyword.known {color: #990073;} -code.lisp .symbol {color: #75a;} -code.lisp .lambda-list {color: #966;} -code.lisp .number {color: #800;} -code.lisp .variable.known {color: #c3c;} -code.lisp .variable.global {color: #939;} -code.lisp .variable.constant {color: #229;} -code.lisp .nil {color: #f00;} -code.lisp .list {color: #222;} +code.hl-highlighted {color: #008080;} +code.hl-highlighted .function {color: #008080;} +code.hl-highlighted .function.known {color: #800603;} +code.hl-highlighted .function.known.special {color: #2d2d2d; font-weight: bold;} +code.hl-highlighted .keyword {color: #990073;} +code.hl-highlighted .keyword.known {color: #990073;} +code.hl-highlighted .symbol {color: #75a;} +code.hl-highlighted .lambda-list {color: #966;} +code.hl-highlighted .number {color: #800;} +code.hl-highlighted .variable.known {color: #c3c;} +code.hl-highlighted .variable.global {color: #939;} +code.hl-highlighted .variable.constant {color: #229;} +code.hl-highlighted .nil {color: #f00;} +code.hl-highlighted .list {color: #222;} + +code.hl-highlighted .string, code.hl-highlighted .string * {color: #d14 !important;} +code.hl-highlighted .comment, +code.hl-highlighted .comment *, +code.hl-highlighted .comment .string +code.hl-highlighted .comment .string * {color: #aaa !important;} +code.hl-highlighted .string .comment {color: #d14 !important;} + +code.hl-highlighted .list.active {display: inline-block; background: #aefff7;} -code.lisp .string, code.lisp .string * {color: #d14 !important;} -code.lisp .comment, -code.lisp .comment *, -code.lisp .comment .string -code.lisp .comment .string * {color: #aaa !important;} diff --git a/js/highlight-lisp/themes/vestigial.css b/js/highlight-lisp/themes/vestigial.css index b022c0b..90c3835 100644 --- a/js/highlight-lisp/themes/vestigial.css +++ b/js/highlight-lisp/themes/vestigial.css @@ -2,17 +2,20 @@ pre { white-space: pre; background-color: #f8f8f8; border: 1px solid #ccc; font- pre code {white-space: pre; margin: 0; padding: 0; background: none; border: none; overflow-x: auto; font-size: 13px;} code {margin: 0 2px; padding: 0 5px; white-space: nowrap; font-family: Consolas, "Liberation Mono", Courier, monospace; background: #f8f8f8; border: 1px solid #eaeaea; border-radius: 3px;} -code.lisp .function.known {color: #a93;} -code.lisp .function.known.special {color: #2a3;} -code.lisp .keyword {color: #7aa;} -code.lisp .keyword.known {color: #4bb;} -code.lisp .symbol {color: #75a;} -code.lisp .lambda-list {color: #966;} -code.lisp .number {color: #800;} -code.lisp .variable.known {color: #c3c;} -code.lisp .variable.global {color: #939;} -code.lisp .variable.constant {color: #229;} -code.lisp .nil {color: #f00;} +code.hl-highlighted .function.known {color: #a93;} +code.hl-highlighted .function.known.special {color: #2a3;} +code.hl-highlighted .keyword {color: #7aa;} +code.hl-highlighted .keyword.known {color: #4bb;} +code.hl-highlighted .symbol {color: #75a;} +code.hl-highlighted .lambda-list {color: #966;} +code.hl-highlighted .number {color: #800;} +code.hl-highlighted .variable.known {color: #c3c;} +code.hl-highlighted .variable.global {color: #939;} +code.hl-highlighted .variable.constant {color: #229;} +code.hl-highlighted .nil {color: #f00;} + +code.hl-highlighted .comment, code.hl-highlighted .comment *, code.hl-highlighted .comment .string {color: #aaa !important;} +code.hl-highlighted .string, code.hl-highlighted .string * {color: #088 !important;} + +code.hl-highlighted .list.active {display: inline-block; background: #aefff7;} -code.lisp .comment, code.lisp .comment *, code.lisp .comment .string {color: #aaa !important;} -code.lisp .string, code.lisp .string * {color: #088 !important;} diff --git a/js/highlight-lisp/themes/wookie.css b/js/highlight-lisp/themes/wookie.css index a82742d..b2962a0 100644 --- a/js/highlight-lisp/themes/wookie.css +++ b/js/highlight-lisp/themes/wookie.css @@ -2,26 +2,30 @@ * Inspired by highlight.js's "Tomorrow night" theme */ pre { white-space: pre; background-color: #1d1f21; border: 0px solid #ccc; font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-radius: 3px; } -pre code.lisp {white-space: pre; margin: 0; padding: 0; background: none; border: none; overflow-x: auto; font-size: 13px;} -code.lisp {margin: 0 2px; padding: 0 5px; white-space: nowrap; font-family: Consolas, "Liberation Mono", Courier, monospace; border: 1px solid #eaeaea; border-radius: 3px;} +pre code.hl-highlighted {white-space: pre; margin: 0; padding: 0; background: none; border: none; overflow-x: auto; font-size: 13px;} +code.hl-highlighted {margin: 0 2px; padding: 0 5px; white-space: nowrap; font-family: Consolas, "Liberation Mono", Courier, monospace; border: 1px solid #eaeaea; border-radius: 3px;} -code.lisp {color: #c5c8c6; color: #c9bf9f;} -code.lisp .function {color: #d9c382;} -code.lisp .function.known {color: #d9c382;} -code.lisp .function.known.special {color: #d9c382; font-weight: bold;} -code.lisp .keyword {color: #74b5ad;} -code.lisp .keyword.known {color: #91b2ce;} -code.lisp .symbol {color: #db919e;} -code.lisp .lambda-list {color: #86adad;} -code.lisp .number {color: #fa879c;} -code.lisp .variable.known {color: #db697e;} -code.lisp .variable.global {color: #96a646;} -code.lisp .variable.constant {color: #96a646;} -code.lisp .nil {color: #db919e; font-weight: bold;} -code.lisp .list {} +code.hl-highlighted {color: #c5c8c6; color: #c9bf9f;} +code.hl-highlighted .function {color: #d9c382;} +code.hl-highlighted .function.known {color: #d9c382;} +code.hl-highlighted .function.known.special {color: #d9c382; font-weight: bold;} +code.hl-highlighted .keyword {color: #74b5ad;} +code.hl-highlighted .keyword.known {color: #91b2ce;} +code.hl-highlighted .symbol {color: #db919e;} +code.hl-highlighted .lambda-list {color: #86adad;} +code.hl-highlighted .number {color: #fa879c;} +code.hl-highlighted .variable.known {color: #db697e;} +code.hl-highlighted .variable.global {color: #96a646;} +code.hl-highlighted .variable.constant {color: #96a646;} +code.hl-highlighted .nil {color: #db919e; font-weight: bold;} +code.hl-highlighted .list {} + +code.hl-highlighted .string, code.hl-highlighted .string * {color: #db7d8e !important;} +code.hl-highlighted .comment, +code.hl-highlighted .comment *, +code.hl-highlighted .comment .string +code.hl-highlighted .comment .string * {color: #777 !important;} +code.hl-highlighted .string .comment {color: #db7d8e !important;} + +code.hl-highlighted .list.active {display: inline-block; color: #333; background: #aaa;} -code.lisp .string, code.lisp .string * {color: #db7d8e !important;} -code.lisp .comment, -code.lisp .comment *, -code.lisp .comment .string -code.lisp .comment .string * {color: #777 !important;}