From bd0c1bede4c83e1a65dff0c0e125331649a4407f Mon Sep 17 00:00:00 2001 From: Josh Goebel Date: Sun, 14 Feb 2021 12:55:43 -0500 Subject: [PATCH 1/7] enh(cpp) Highlight all function dispatches --- CHANGES.md | 1 + src/languages/cpp.js | 15 +++++++++++++++ test/markup/cpp/function-declarations.expect.txt | 3 ++- test/markup/cpp/preprocessor.expect.txt | 2 +- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index f86c45c1f1..68b4688efb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,7 @@ New Languages: Language grammar improvements: +- enh(cpp) Highlight all function dispatches (#) [Josh Goebel][] - enh(gml) Add additional GML 2.3 keywords (#2984) [xDGameStudios][] - fix(cpp) constructor support for initializers (#3001) [Josh Goebel][] - enh(php) Add `trait` to class-like naming patterns (#2997) [Ayesh][] diff --git a/src/languages/cpp.js b/src/languages/cpp.js index 3751c9bba2..341427c796 100644 --- a/src/languages/cpp.js +++ b/src/languages/cpp.js @@ -172,6 +172,17 @@ export default function(hljs) { relevance: 0 }; + const FUNCTION_DISPATCH = { + className: "function.dispatch", + begin: regex.concat( + /\b/, + /(?!decltype)/, + /(?!if)/, + /(?!for)/, + /(?!while)/, + hljs.IDENT_RE + '\\s*', regex.lookahead(/\(/)) + }; + const FUNCTION_DECLARATION = { className: 'function', begin: '(' + FUNCTION_TYPE_RE + '[\\*&\\s]+)+' + FUNCTION_TITLE, @@ -256,9 +267,13 @@ export default function(hljs) { ], keywords: CPP_KEYWORDS, illegal: 'template<typename T...> void foo(T... args) {} -test(); +test(); void A(): a(10) {} explicit A(): a(10) {} + diff --git a/test/markup/cpp/preprocessor.expect.txt b/test/markup/cpp/preprocessor.expect.txt index fa1e10f82d..9b90fe24d8 100644 --- a/test/markup/cpp/preprocessor.expect.txt +++ b/test/markup/cpp/preprocessor.expect.txt @@ -20,7 +20,7 @@ if (p) { #ifdef DEBUG - onething(); + onething(); #endif } else if (errno) { #ifdef DEBUG From 184424de3aaa36d91427650bcdb6cc02a3a444ff Mon Sep 17 00:00:00 2001 From: Josh Goebel Date: Sun, 14 Feb 2021 13:00:49 -0500 Subject: [PATCH 2/7] pr # --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 68b4688efb..9ca817bac3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,7 +12,7 @@ New Languages: Language grammar improvements: -- enh(cpp) Highlight all function dispatches (#) [Josh Goebel][] +- enh(cpp) Highlight all function dispatches (#3005) [Josh Goebel][] - enh(gml) Add additional GML 2.3 keywords (#2984) [xDGameStudios][] - fix(cpp) constructor support for initializers (#3001) [Josh Goebel][] - enh(php) Add `trait` to class-like naming patterns (#2997) [Ayesh][] From 4769fef7c52f135aa5b957093a6001a90fb35d40 Mon Sep 17 00:00:00 2001 From: Josh Goebel Date: Mon, 15 Feb 2021 08:11:39 -0500 Subject: [PATCH 3/7] convert built-ins to common hints --- src/highlight.js | 9 ++- src/languages/cpp.js | 133 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 131 insertions(+), 11 deletions(-) diff --git a/src/highlight.js b/src/highlight.js index 0455377d04..0278465da1 100644 --- a/src/highlight.js +++ b/src/highlight.js @@ -172,8 +172,13 @@ const HLJS = function(hljs) { buf = ""; relevance += keywordRelevance; - const cssClass = language.classNameAliases[kind] || kind; - emitter.addKeyword(match[0], cssClass); + if (kind === "_") { + // _ is magic identifier for relevance only, do not highlight + buf += match[0]; + } else { + const cssClass = language.classNameAliases[kind] || kind; + emitter.addKeyword(match[0], cssClass); + } } else { buf += match[0]; } diff --git a/src/languages/cpp.js b/src/languages/cpp.js index 341427c796..f7a76e5dfd 100644 --- a/src/languages/cpp.js +++ b/src/languages/cpp.js @@ -107,6 +107,122 @@ export default function(hljs) { const FUNCTION_TITLE = regex.optional(NAMESPACE_RE) + hljs.IDENT_RE + '\\s*\\('; + const COMMON_CPP_HINTS = [ + 'asin', + 'atan2', + 'atan', + 'calloc', + 'ceil', + 'cosh', + 'cos', + 'exit', + 'exp', + 'fabs', + 'floor', + 'fmod', + 'fprintf', + 'fputs', + 'free', + 'frexp', + 'auto_ptr', + 'deque', + 'list', + 'queue', + 'stack', + 'vector', + 'map', + 'set', + 'pair', + 'bitset', + 'multiset', + 'multimap', + 'unordered_set', + 'fscanf', + 'future', + 'isalnum', + 'isalpha', + 'iscntrl', + 'isdigit', + 'isgraph', + 'islower', + 'isprint', + 'ispunct', + 'isspace', + 'isupper', + 'isxdigit', + 'tolower', + 'toupper', + 'labs', + 'ldexp', + 'log10', + 'log', + 'malloc', + 'realloc', + 'memchr', + 'memcmp', + 'memcpy', + 'memset', + 'modf', + 'pow', + 'printf', + 'putchar', + 'puts', + 'scanf', + 'sinh', + 'sin', + 'snprintf', + 'sprintf', + 'sqrt', + 'sscanf', + 'strcat', + 'strchr', + 'strcmp', + 'strcpy', + 'strcspn', + 'strlen', + 'strncat', + 'strncmp', + 'strncpy', + 'strpbrk', + 'strrchr', + 'strspn', + 'strstr', + 'tanh', + 'tan', + 'unordered_map', + 'unordered_multiset', + 'unordered_multimap', + 'priority_queue', + 'make_pair', + 'array', + 'shared_ptr', + 'abort', + 'terminate', + 'abs', + 'acos', + 'vfprintf', + 'vprintf', + 'vsprintf', + 'endl', + 'initializer_list', + 'unique_ptr', + 'complex', + 'imaginary', + 'std', + 'string', + 'wstring', + 'cin', + 'cout', + 'cerr', + 'clog', + 'stdin', + 'stdout', + 'stderr', + 'stringstream', + 'istringstream', + 'ostringstream' + ]; + const CPP_KEYWORDS = { keyword: 'int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof ' + 'dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace ' + @@ -120,15 +236,9 @@ export default function(hljs) { 'atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong ' + 'atomic_ullong new throw return ' + 'and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq', - built_in: 'std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream ' + - 'auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set ' + - 'unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos ' + - 'asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp ' + - 'fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper ' + - 'isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow ' + - 'printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp ' + - 'strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan ' + - 'vfprintf vprintf vsprintf endl initializer_list unique_ptr _Bool complex _Complex imaginary _Imaginary', + built_in: '_Bool _Complex _Imaginary', + // used only for relevance + _: COMMON_CPP_HINTS, literal: 'true false nullptr NULL' }; @@ -174,6 +284,11 @@ export default function(hljs) { const FUNCTION_DISPATCH = { className: "function.dispatch", + relevance: 0, + keywords: { + // used only for relevance + _: COMMON_CPP_HINTS + }, begin: regex.concat( /\b/, /(?!decltype)/, From 842ea576f5922796e988193ad780aa5c3b274bc3 Mon Sep 17 00:00:00 2001 From: Josh Goebel Date: Mon, 15 Feb 2021 08:26:39 -0500 Subject: [PATCH 4/7] update tests --- src/languages/cpp.js | 36 ++++++++++--------- test/markup/arduino/default.expect.txt | 10 +++--- .../cpp/function-declarations.expect.txt | 4 +-- test/markup/cpp/function-title.expect.txt | 10 +++--- test/markup/cpp/preprocessor.expect.txt | 2 +- .../markup/cpp/template_complexity.expect.txt | 8 ++--- 6 files changed, 37 insertions(+), 33 deletions(-) diff --git a/src/languages/cpp.js b/src/languages/cpp.js index f7a76e5dfd..8a1146a6b2 100644 --- a/src/languages/cpp.js +++ b/src/languages/cpp.js @@ -242,7 +242,26 @@ export default function(hljs) { literal: 'true false nullptr NULL' }; + const FUNCTION_DISPATCH = { + className: "function.dispatch", + relevance: 0, + // keywords: { + // // used only for relevance + // _: COMMON_CPP_HINTS + // }, + keywords: CPP_KEYWORDS, + begin: regex.concat( + /\b/, + /(?!decltype)/, + /(?!if)/, + /(?!for)/, + /(?!while)/, + hljs.IDENT_RE, + regex.lookahead(/\s*\(/)) + }; + const EXPRESSION_CONTAINS = [ + FUNCTION_DISPATCH, PREPROCESSOR, CPP_PRIMITIVE_TYPES, C_LINE_COMMENT_MODE, @@ -251,6 +270,7 @@ export default function(hljs) { STRINGS ]; + const EXPRESSION_CONTEXT = { // This mode covers expression context where we can't expect a function // definition and shouldn't highlight anything that looks like one: @@ -282,22 +302,6 @@ export default function(hljs) { relevance: 0 }; - const FUNCTION_DISPATCH = { - className: "function.dispatch", - relevance: 0, - keywords: { - // used only for relevance - _: COMMON_CPP_HINTS - }, - begin: regex.concat( - /\b/, - /(?!decltype)/, - /(?!if)/, - /(?!for)/, - /(?!while)/, - hljs.IDENT_RE + '\\s*', regex.lookahead(/\(/)) - }; - const FUNCTION_DECLARATION = { className: 'function', begin: '(' + FUNCTION_TYPE_RE + '[\\*&\\s]+)+' + FUNCTION_TITLE, diff --git a/test/markup/arduino/default.expect.txt b/test/markup/arduino/default.expect.txt index 1e6a196047..7080eab6a5 100644 --- a/test/markup/arduino/default.expect.txt +++ b/test/markup/arduino/default.expect.txt @@ -12,14 +12,14 @@ // the setup routine runs once when you press reset: void setup() { // initialize the digital pin as an output. - pinMode(led, OUTPUT); + pinMode(led, OUTPUT); } // the loop routine runs over and over again forever: void loop() { - digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) - delay(1000); // wait for a second - digitalWrite(led, LOW); // turn the LED off by making the voltage LOW - delay(1000); // wait for a second + digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) + delay(1000); // wait for a second + digitalWrite(led, LOW); // turn the LED off by making the voltage LOW + delay(1000); // wait for a second } diff --git a/test/markup/cpp/function-declarations.expect.txt b/test/markup/cpp/function-declarations.expect.txt index 91bb65c239..ee2e15f2d0 100644 --- a/test/markup/cpp/function-declarations.expect.txt +++ b/test/markup/cpp/function-declarations.expect.txt @@ -1,5 +1,5 @@ -decltype(auto) look_up_a_string_1() { return lookup1(); } -void look_up_a_string_2() { return lookup2(); } +decltype(auto) look_up_a_string_1() { return lookup1(); } +void look_up_a_string_2() { return lookup2(); } friend void A::showB(B x) {} friend void showB(B x) {} friend void showB(B::SomeType x) {} diff --git a/test/markup/cpp/function-title.expect.txt b/test/markup/cpp/function-title.expect.txt index 750081e477..e94c2295e9 100644 --- a/test/markup/cpp/function-title.expect.txt +++ b/test/markup/cpp/function-title.expect.txt @@ -1,9 +1,9 @@ int main() { - A a = new A(); - int b = b * sum(1, 2); - if (a->check1()) + A a = new A(); + int b = b * sum(1, 2); + if (a->check1()) return 3; - else if (a->check2()) + else if (a->check2()) return 4; - return a->result(); + return a->result(); } diff --git a/test/markup/cpp/preprocessor.expect.txt b/test/markup/cpp/preprocessor.expect.txt index 9b90fe24d8..5b3b9ad3df 100644 --- a/test/markup/cpp/preprocessor.expect.txt +++ b/test/markup/cpp/preprocessor.expect.txt @@ -24,7 +24,7 @@ #endif } else if (errno) { #ifdef DEBUG - anotherthing(); + anotherthing(); #endif } diff --git a/test/markup/cpp/template_complexity.expect.txt b/test/markup/cpp/template_complexity.expect.txt index 0dbe6c993b..24cd93c78e 100644 --- a/test/markup/cpp/template_complexity.expect.txt +++ b/test/markup/cpp/template_complexity.expect.txt @@ -3,14 +3,14 @@ namespace impl { template<typename T> - struct is_streamable<T, std::void_t<decltype(std::declval<std::wostream &>() << std::declval<T>())>> : std::true_type { }; + struct is_streamable<T, std::void_t<decltype(std::declval<std::wostream &>() << std::declval<T>())>> : std::true_type { }; } // Disable overload for already valid operands. -template<class T, class = std::enable_if_t<!impl::is_streamable_v<const T &> && std::is_convertible_v<const T &, std::wstring_view>>> -std::wostream &operator <<(std::wostream &stream, const T &thing) +template<class T, class = std::enable_if_t<!impl::is_streamable_v<const T &> && std::is_convertible_v<const T &, std::wstring_view>>> +std::wostream &operator <<(std::wostream &stream, const T &thing) { - return stream << static_cast<std::wstring_view>(thing); + return stream << static_cast<std::wstring_view>(thing); } enum struct DataHolder { }; From d591a7324bcf0e3b7cd3bbd1d706353841d7e228 Mon Sep 17 00:00:00 2001 From: Josh Goebel Date: Mon, 15 Feb 2021 08:32:39 -0500 Subject: [PATCH 5/7] fix arduino to use function dispatch also --- src/languages/arduino.js | 6 ++++-- test/markup/arduino/default.expect.txt | 10 +++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/languages/arduino.js b/src/languages/arduino.js index a706ad6ff5..872991ab09 100644 --- a/src/languages/arduino.js +++ b/src/languages/arduino.js @@ -13,7 +13,6 @@ export default function(hljs) { keyword: 'boolean byte word String', built_in: - 'setup loop ' + 'KeyboardController MouseController SoftwareSerial ' + 'EthernetServer EthernetClient LiquidCrystal ' + 'RobotControl GSMVoiceCall EthernetUDP EsploraTFT ' + @@ -24,7 +23,9 @@ export default function(hljs) { 'WiFiUDP GSM_SMS Mailbox USBHost Firmata PImage ' + 'Client Server GSMPIN FileIO Bridge Serial ' + 'EEPROM Stream Mouse Audio Servo File Task ' + - 'GPRS WiFi Wire TFT GSM SPI SD ' + + 'GPRS WiFi Wire TFT GSM SPI SD ', + _: + 'setup loop ' + 'runShellCommandAsynchronously analogWriteResolution ' + 'retrieveCallingNumber printFirmwareVersion ' + 'analogReadResolution sendDigitalPortPair ' + @@ -102,6 +103,7 @@ export default function(hljs) { kws.keyword += ' ' + ARDUINO_KW.keyword; kws.literal += ' ' + ARDUINO_KW.literal; kws.built_in += ' ' + ARDUINO_KW.built_in; + kws._ += ' ' + ARDUINO_KW._; ARDUINO.name = 'Arduino'; ARDUINO.aliases = ['ino']; diff --git a/test/markup/arduino/default.expect.txt b/test/markup/arduino/default.expect.txt index 7080eab6a5..1e6a196047 100644 --- a/test/markup/arduino/default.expect.txt +++ b/test/markup/arduino/default.expect.txt @@ -12,14 +12,14 @@ // the setup routine runs once when you press reset: void setup() { // initialize the digital pin as an output. - pinMode(led, OUTPUT); + pinMode(led, OUTPUT); } // the loop routine runs over and over again forever: void loop() { - digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) - delay(1000); // wait for a second - digitalWrite(led, LOW); // turn the LED off by making the voltage LOW - delay(1000); // wait for a second + digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) + delay(1000); // wait for a second + digitalWrite(led, LOW); // turn the LED off by making the voltage LOW + delay(1000); // wait for a second } From 210a91e127d075c0dae3828facec4253075cc709 Mon Sep 17 00:00:00 2001 From: Josh Goebel Date: Fri, 5 Mar 2021 16:07:12 -0500 Subject: [PATCH 6/7] document the keywords _ident behavior --- docs/language-guide.rst | 6 ++++-- src/highlight.js | 5 +++-- src/languages/cpp.js | 3 +-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/language-guide.rst b/docs/language-guide.rst index 7ec0d62053..5e622be1af 100644 --- a/docs/language-guide.rst +++ b/docs/language-guide.rst @@ -87,12 +87,14 @@ object, each property of which defines its own group of keywords: { keywords: { keyword: 'else for if while', - literal: ['false','true','null'] + literal: ['false','true','null'], + _relevance_only: 'one two three four' } } The group name becomes the class name in the generated markup, enabling different -theming for different kinds of keywords. +theming for different kinds of keywords. Any property starting with a ``_`` will +only use those keywords to increase relevance, they will not be highlighted. To detect keywords, highlight.js breaks the processed chunk of code into separate words — a process called lexing. By default, "words" are matched with the regexp diff --git a/src/highlight.js b/src/highlight.js index 0278465da1..49d974af18 100644 --- a/src/highlight.js +++ b/src/highlight.js @@ -172,8 +172,9 @@ const HLJS = function(hljs) { buf = ""; relevance += keywordRelevance; - if (kind === "_") { - // _ is magic identifier for relevance only, do not highlight + if (kind.startsWith("_")) { + // _ implied for relevance only, do not highlight + // by applying a class name buf += match[0]; } else { const cssClass = language.classNameAliases[kind] || kind; diff --git a/src/languages/cpp.js b/src/languages/cpp.js index 8a1146a6b2..4838a3b3c5 100644 --- a/src/languages/cpp.js +++ b/src/languages/cpp.js @@ -237,8 +237,7 @@ export default function(hljs) { 'atomic_ullong new throw return ' + 'and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq', built_in: '_Bool _Complex _Imaginary', - // used only for relevance - _: COMMON_CPP_HINTS, + _relevance_hints: COMMON_CPP_HINTS, literal: 'true false nullptr NULL' }; From 8e4577becd5a595b1e948f7f464eec33fa3761b8 Mon Sep 17 00:00:00 2001 From: Josh Goebel Date: Fri, 5 Mar 2021 16:15:49 -0500 Subject: [PATCH 7/7] dead comments --- src/languages/cpp.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/languages/cpp.js b/src/languages/cpp.js index 4838a3b3c5..e7ffaab34c 100644 --- a/src/languages/cpp.js +++ b/src/languages/cpp.js @@ -244,10 +244,6 @@ export default function(hljs) { const FUNCTION_DISPATCH = { className: "function.dispatch", relevance: 0, - // keywords: { - // // used only for relevance - // _: COMMON_CPP_HINTS - // }, keywords: CPP_KEYWORDS, begin: regex.concat( /\b/,