From 3d5d9a4af38facd8c2d79abbe74ead61470ca97b Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke <marijnh@gmail.com> Date: Mon, 18 May 2015 12:39:23 +0200 Subject: [PATCH] [clike mode] Highlight identifiers that are (probably) definitions --- mode/clike/clike.js | 40 ++++++++++++++++++++++++++++++++-------- mode/clike/test.js | 9 +++++++-- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/mode/clike/clike.js b/mode/clike/clike.js index 09a4237c..c5469eb2 100644 --- a/mode/clike/clike.js +++ b/mode/clike/clike.js @@ -19,6 +19,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { types = parserConfig.types || {}, builtin = parserConfig.builtin || {}, blockKeywords = parserConfig.blockKeywords || {}, + defKeywords = parserConfig.defKeywords || {}, atoms = parserConfig.atoms || {}, hooks = parserConfig.hooks || {}, multiLineStrings = parserConfig.multiLineStrings, @@ -26,7 +27,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { indentSwitch = parserConfig.indentSwitch !== false; var isOperatorChar = /[+\-*&%=<>!?|\/]/; - var curPunc; + var curPunc, isDefKeyword; function tokenBase(stream, state) { var ch = stream.next(); @@ -64,9 +65,10 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { var cur = stream.current(); if (keywords.propertyIsEnumerable(cur)) { if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; + if (defKeywords.propertyIsEnumerable(cur)) isDefKeyword = true; return "keyword"; } - if (types.propertyIsEnumerable(cur)) return "variable-2"; + if (types.propertyIsEnumerable(cur)) return "variable-3"; if (builtin.propertyIsEnumerable(cur)) { if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; return "builtin"; @@ -123,6 +125,11 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { return state.context = state.context.prev; } + function typeBefore(stream, state) { + if (state.prevToken == "variable" || state.prevToken == "variable-3") return true; + if (/\S[>*\]]\s*$|\*$/.test(stream.string.slice(0, stream.start))) return true; + } + // Interface return { @@ -144,7 +151,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { state.startOfLine = true; } if (stream.eatSpace()) return null; - curPunc = null; + curPunc = isDefKeyword = null; var style = (state.tokenize || tokenBase)(stream, state); if (style == "comment" || style == "meta") return style; if (ctx.align == null) ctx.align = true; @@ -167,8 +174,16 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { type = "switchstatement" pushContext(state, stream.column(), type); } + + if (style == "variable" && + ((state.prevToken == "def" || + (parserConfig.typeFirstDefinitions && typeBefore(stream, state) && + stream.match(/^\s*\(/, false))))) + style = "def"; + state.startOfLine = false; - return state.prevToken = style; + state.prevToken = isDefKeyword ? "def" : style; + return style; }, indent: function(state, textAfter) { @@ -202,7 +217,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { return obj; } var cKeywords = "auto if break case register continue return default do sizeof " + - "static else struct switch extern typedef float union for unsigned " + + "static else struct switch extern typedef float union for " + "goto while enum const volatile true false"; var cTypes = "int long char short double float unsigned signed void size_t ptrdiff_t"; @@ -224,8 +239,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { return "meta"; } - function pointerHook(stream, state) { - if (state.prevToken == "variable-2") return "variable-2"; + function pointerHook(_stream, state) { + if (state.prevToken == "variable-3") return "variable-3"; return false; } @@ -305,6 +320,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { "int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t " + "uint32_t uint64_t"), blockKeywords: words("case do else for if switch while struct"), + defKeywords: words("struct"), + typeFirstDefinitions: true, atoms: words("null"), hooks: {"#": cppHook, "*": pointerHook}, modeProps: {fold: ["brace", "include"]} @@ -319,6 +336,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { "static_assert override"), types: words(cTypes + "bool wchar_t"), blockKeywords: words("catch class do else finally for if struct switch try while"), + defKeywords: words("class namespace struct enum union"), + typeFirstDefinitions: true, atoms: words("true false null"), hooks: { "#": cppHook, @@ -341,6 +360,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { types: words("byte short int long float double boolean char void Boolean Byte Character Double Float " + "Integer Long Number Object Short String StringBuffer StringBuilder Void"), blockKeywords: words("catch class do else finally for if switch try while"), + defKeywords: words("class interface package enum"), + typeFirstDefinitions: true, atoms: words("true false null"), hooks: { "@": function(stream) { @@ -365,6 +386,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { " UInt64 bool byte char decimal double short int long object" + " sbyte float string ushort uint ulong"), blockKeywords: words("catch class do else finally for foreach if struct switch try while"), + defKeywords: words("class interface namespace struct var"), + typeFirstDefinitions: true, atoms: words("true false null"), hooks: { "@": function(stream, state) { @@ -397,7 +420,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { /* scala */ "abstract case catch class def do else extends false final finally for forSome if " + "implicit import lazy match new null object override package private protected return " + - "sealed super this throw trait try trye type val var while with yield _ : = => <- <: " + + "sealed super this throw trait try type val var while with yield _ : = => <- <: " + "<% >: # @ " + /* package scala */ @@ -421,6 +444,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) { ), multiLineStrings: true, blockKeywords: words("catch class do else finally for forSome if match switch try while"), + defKeywords: words("class def object package trait type val var"), atoms: words("true false null"), indentStatements: false, indentSwitch: false, diff --git a/mode/clike/test.js b/mode/clike/test.js index ee885505..801a17c5 100644 --- a/mode/clike/test.js +++ b/mode/clike/test.js @@ -6,8 +6,8 @@ function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } MT("indent", - "[variable-2 void] [variable foo]([variable-2 void*] [variable a], [variable-2 int] [variable b]) {", - " [variable-2 int] [variable c] [operator =] [variable b] [operator +]", + "[variable-3 void] [def foo]([variable-3 void*] [variable a], [variable-3 int] [variable b]) {", + " [variable-3 int] [variable c] [operator =] [variable b] [operator +]", " [number 1];", " [keyword return] [operator *][variable a];", "}"); @@ -19,4 +19,9 @@ " [keyword default]:", " [variable printf]([string \"foo %c\"], [variable x]);", "}"); + + MT("def", + "[variable-3 void] [def foo]() {}", + "[keyword struct] [def bar]{}", + "[variable-3 int] [variable-3 *][def baz]() {}"); })(); -- GitLab