Skip to content

Commit

Permalink
enh(parser) multi-class in a single mode
Browse files Browse the repository at this point in the history
  • Loading branch information
joshgoebel committed Mar 27, 2021
1 parent 8e024dd commit 75bc34f
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 6 deletions.
25 changes: 22 additions & 3 deletions src/highlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,11 +246,30 @@ const HLJS = function(hljs) {
modeBuffer = '';
}

/**
* @param {Mode} mode
* @param {EnhancedMatch} match
*/
function emitMultiClass(mode, match) {
let i = 1;
while (match[i]) {
const klass = mode.className[i];
const text = match[i];
if (klass) { emitter.addKeyword(text, klass); } else { emitter.addText(text); }
i++;
}
}

/**
* @param {Mode} mode - new mode to start
* @param {EnhancedMatch} match
*/
function startNewMode(mode) {
if (mode.className) {
function startNewMode(mode, match) {
if (mode.isMultiClass) {
// at this point modeBuffer should just be the match
modeBuffer = "";
emitMultiClass(mode, match);
} else if (mode.className) {
emitter.openNode(language.classNameAliases[mode.className] || mode.className);
}
top = Object.create(mode, { parent: { value: top } });
Expand Down Expand Up @@ -340,7 +359,7 @@ const HLJS = function(hljs) {
modeBuffer = lexeme;
}
}
startNewMode(newMode);
startNewMode(newMode, match);
// if (mode["after:begin"]) {
// let resp = new Response(mode);
// mode["after:begin"](match, resp);
Expand Down
13 changes: 11 additions & 2 deletions src/languages/vim.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Website: https://www.vim.org
Category: scripting
*/

import * as regex from '../lib/regex.js';

export default function(hljs) {
return {
name: 'Vim Script',
Expand Down Expand Up @@ -99,8 +101,15 @@ export default function(hljs) {
begin: /[bwtglsav]:[\w\d_]+/
},
{
className: 'function',
beginKeywords: 'function function!',
begin: [
/function|function!/,
/\s+/,
hljs.IDENT_RE
],
className: {
1: "keyword",
3: "title"
},
end: '$',
relevance: 0,
contains: [
Expand Down
27 changes: 27 additions & 0 deletions src/lib/ext/multi_class.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* eslint-disable no-throw-literal */
import * as regex from "../regex.js";

const MultiClassError = new Error();

/**
*
* @param {CompiledMode} mode
*/
export function MultiClass(mode) {
if (!Array.isArray(mode.begin)) return;

if (mode.skip || mode.excludeBegin || mode.returnBegin) {
console.error("skip, excludeBegin, returnBegin not compatible with multi-class")
throw MultiClassError;
}

if (typeof mode.className !== "object") {
console.error("className must be object or array");
throw MultiClassError;
}

const items = mode.begin.map(x => regex.concat("(", x, ")"));
mode.begin = regex.concat(...items);
mode.isMultiClass = true;

}
4 changes: 3 additions & 1 deletion src/lib/mode_compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as regex from './regex.js';
import { inherit } from './utils.js';
import * as EXT from "./compiler_extensions.js";
import { compileKeywords } from "./compile_keywords.js";
import { MultiClass } from "./ext/multi_class.js";

// compilation

Expand Down Expand Up @@ -284,7 +285,8 @@ export function compileLanguage(language, { plugins }) {
[
// do this early so compiler extensions generally don't have to worry about
// the distinction between match/begin
EXT.compileMatch
EXT.compileMatch,
MultiClass
].forEach(ext => ext(mode, parent));

language.compilerExtensions.forEach(ext => ext(mode, parent));
Expand Down

0 comments on commit 75bc34f

Please sign in to comment.