From 87bd22b541cea0929bacd8624d7d2ef466d7928f Mon Sep 17 00:00:00 2001 From: Josh Goebel Date: Tue, 28 Apr 2020 17:17:13 -0400 Subject: [PATCH] smarter shebang --- src/languages/bash.js | 7 +++---- src/languages/hy.js | 7 +------ src/languages/javascript.js | 8 ++++---- src/languages/lisp.js | 6 +----- src/languages/scheme.js | 8 +------- src/languages/typescript.js | 1 + src/lib/modes.js | 21 +++++++++++++++++++++ src/lib/regex.js | 5 +++++ 8 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/languages/bash.js b/src/languages/bash.js index be9c8c92fc..4562fc15dd 100644 --- a/src/languages/bash.js +++ b/src/languages/bash.js @@ -55,11 +55,10 @@ export default function(hljs) { VAR ] }; - const SHEBANG = { - className: 'meta', - begin: /^#![^\n]+sh\s*$/, + const SHEBANG = hljs.SHEBANG({ + binary: /(fish|bash|zsh|sh)/, relevance: 10 - }; + }); const FUNCTION = { className: 'function', begin: /\w[\w\d_]*\s*\(\s*\)\s*\{/, diff --git a/src/languages/hy.js b/src/languages/hy.js index 4faa8780f8..027502a6c6 100644 --- a/src/languages/hy.js +++ b/src/languages/hy.js @@ -45,11 +45,6 @@ export default function(hljs) { var SYMBOL_RE = '[' + SYMBOLSTART + '][' + SYMBOLSTART + '0-9/;:]*'; var SIMPLE_NUMBER_RE = '[-+]?\\d+(\\.\\d+)?'; - var SHEBANG = { - className: 'meta', - begin: '^#!', end: '$' - }; - var SYMBOL = { begin: SYMBOL_RE, relevance: 0 @@ -105,6 +100,6 @@ export default function(hljs) { name: 'Hy', aliases: ['hylang'], illegal: /\S/, - contains: [SHEBANG, LIST, STRING, HINT, HINT_COL, COMMENT, KEY, COLLECTION, NUMBER, LITERAL] + contains: [hljs.SHEBANG(), LIST, STRING, HINT, HINT_COL, COMMENT, KEY, COLLECTION, NUMBER, LITERAL] } } diff --git a/src/languages/javascript.js b/src/languages/javascript.js index 432863359e..9f900569c2 100644 --- a/src/languages/javascript.js +++ b/src/languages/javascript.js @@ -97,15 +97,15 @@ export default function(hljs) { aliases: ['js', 'jsx', 'mjs', 'cjs'], keywords: KEYWORDS, contains: [ + hljs.SHEBANG({ + binary: "node", + relevance: 5 + }), { className: 'meta', relevance: 10, begin: /^\s*['"]use (strict|asm)['"]/ }, - { - className: 'meta', - begin: /^#!/, end: /$/ - }, hljs.APOS_STRING_MODE, hljs.QUOTE_STRING_MODE, HTML_TEMPLATE, diff --git a/src/languages/lisp.js b/src/languages/lisp.js index c8305f6bea..5b505cd1a5 100644 --- a/src/languages/lisp.js +++ b/src/languages/lisp.js @@ -9,10 +9,6 @@ export default function(hljs) { var LISP_IDENT_RE = '[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*'; var MEC_RE = '\\|[^]*?\\|'; var LISP_SIMPLE_NUMBER_RE = '(\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s|D|E|F|L|S)(\\+|\\-)?\\d+)?'; - var SHEBANG = { - className: 'meta', - begin: '^#!', end: '$' - }; var LITERAL = { className: 'literal', begin: '\\b(t{1}|nil)\\b' @@ -97,7 +93,7 @@ export default function(hljs) { illegal: /\S/, contains: [ NUMBER, - SHEBANG, + hljs.SHEBANG(), LITERAL, STRING, COMMENT, diff --git a/src/languages/scheme.js b/src/languages/scheme.js index 335c8e14d0..df26b7cf73 100644 --- a/src/languages/scheme.js +++ b/src/languages/scheme.js @@ -50,12 +50,6 @@ export default function(hljs) { 'with-input-from-file with-output-to-file write write-char zero?' }; - var SHEBANG = { - className: 'meta', - begin: '^#!', - end: '$' - }; - var LITERAL = { className: 'literal', begin: '(#t|#f|#\\\\' + SCHEME_IDENT_RE + '|#\\\\.)' @@ -150,6 +144,6 @@ export default function(hljs) { return { name: 'Scheme', illegal: /\S/, - contains: [SHEBANG, NUMBER, STRING, QUOTED_IDENT, QUOTED_LIST, LIST].concat(COMMENT_MODES) + contains: [hljs.SHEBANG(), NUMBER, STRING, QUOTED_IDENT, QUOTED_LIST, LIST].concat(COMMENT_MODES) }; } diff --git a/src/languages/typescript.js b/src/languages/typescript.js index adfed257d3..f830428477 100644 --- a/src/languages/typescript.js +++ b/src/languages/typescript.js @@ -127,6 +127,7 @@ export default function(hljs) { aliases: ['ts'], keywords: KEYWORDS, contains: [ + hljs.SHEBANG(), { className: 'meta', begin: /^\s*['"]use strict['"]/ diff --git a/src/lib/modes.js b/src/lib/modes.js index 8acb8f0e51..4f1ea0efd2 100644 --- a/src/lib/modes.js +++ b/src/lib/modes.js @@ -1,4 +1,5 @@ import { inherit } from './utils'; +import * as regex from './regex'; // Common regexps export const IDENT_RE = '[a-zA-Z]\\w*'; @@ -8,6 +9,26 @@ export const C_NUMBER_RE = '(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+ export const BINARY_NUMBER_RE = '\\b(0b[01]+)'; // 0b... export const RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~'; +export const SHEBANG = (opts = {}) => { + if (opts.binary) { + opts.begin = regex.concat( + /^#!\//, + /.*/, + opts.binary, + /\b.*/); + } + return inherit({ + className: 'meta', + begin: /^#!\//, + end: /$/, + illegal: '\\n', + relevance: 0, + "on:begin": (m, resp) => { + if (m.index !== 0) resp.ignoreMatch(); + } + }, opts); +}; + // Common modes export const BACKSLASH_ESCAPE = { begin: '\\\\[\\s\\S]', relevance: 0 diff --git a/src/lib/regex.js b/src/lib/regex.js index c349485eaf..003dc9cbca 100644 --- a/src/lib/regex.js +++ b/src/lib/regex.js @@ -8,6 +8,11 @@ export function source(re) { return (re && re.source) || re; } +export function concat(...args) { + const joined = args.map((x) => source(x)).join(""); + return joined; +} + export function countMatchGroups(re) { return (new RegExp(re.toString() + '|')).exec('').length - 1; }