From 28bc0e0361ef3002fc79513831c69a1b7f57bc59 Mon Sep 17 00:00:00 2001
From: pabloferz <pabloferz@yahoo.com.mx>
Date: Wed, 23 Dec 2015 00:46:40 +0100
Subject: [PATCH] [julia mode] String, function calls and definitions
 improvements

---
 mode/julia/julia.js | 96 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 78 insertions(+), 18 deletions(-)

diff --git a/mode/julia/julia.js b/mode/julia/julia.js
index e31b44a3c..ca672b9ed 100644
--- a/mode/julia/julia.js
+++ b/mode/julia/julia.js
@@ -69,12 +69,12 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {
     }
 
     // Handle scope changes
-    var leaving_expr = state.leaving_expr;
+    var leavingExpr = state.leavingExpr;
     if (stream.sol()) {
-      leaving_expr = false;
+      leavingExpr = false;
     }
-    state.leaving_expr = false;
-    if (leaving_expr) {
+    state.leavingExpr = false;
+    if (leavingExpr) {
       if (stream.match(/^'+/)) {
         return 'operator';
       }
@@ -108,16 +108,16 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {
 
     if (scope === '[' && ch === ']') {
       state.scopes.pop();
-      state.leaving_expr = true;
+      state.leavingExpr = true;
     }
 
     if (scope === '{' && ch === '}') {
       state.scopes.pop();
-      state.leaving_expr = true;
+      state.leavingExpr = true;
     }
 
     if (ch === ')') {
-      state.leaving_expr = true;
+      state.leavingExpr = true;
     }
 
     var match;
@@ -142,7 +142,6 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {
       return 'operator';
     }
 
-
     // Handle Number Literals
     if (stream.match(/^[0-9\.]/, false)) {
       var imMatcher = RegExp(/^im\b/);
@@ -155,7 +154,7 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {
       if (floatLiteral) {
           // Float literals may be "imaginary"
           stream.match(imMatcher);
-          state.leaving_expr = true;
+          state.leavingExpr = true;
           return 'number';
       }
       // Integers
@@ -175,7 +174,7 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {
       if (intLiteral) {
           // Integer literals may be "long"
           stream.match(imMatcher);
-          state.leaving_expr = true;
+          state.leavingExpr = true;
           return 'number';
       }
     }
@@ -189,7 +188,7 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {
     }
 
     // Handle symbols
-    if (!leaving_expr && stream.match(symbol)) {
+    if (!leavingExpr && stream.match(symbol)) {
       return 'builtin';
     }
 
@@ -225,8 +224,25 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {
       return 'builtin';
     }
 
+    var isDefinition = state.isDefinition ||
+                       state.lastToken == 'function' ||
+                       state.lastToken == 'macro' ||
+                       state.lastToken == 'type' ||
+                       state.lastToken == 'immutable';
+
     if (stream.match(identifiers)) {
-      state.leaving_expr = true;
+      if (isDefinition) {
+        if (stream.peek() === '.') {
+          state.isDefinition = true;
+          return 'variable';
+        }
+        state.isDefinition = false;
+        return 'def';
+      }
+      if (stream.match(/^({[^}]*})*\(/, false)) {
+        return callOrDef(stream, state);
+      }
+      state.leavingExpr = true;
       return 'variable';
     }
 
@@ -235,11 +251,47 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {
     return ERRORCLASS;
   }
 
+  function callOrDef(stream, state) {
+    var match = stream.match(/^(\(\s*)/);
+    if (match) {
+      if (state.firstParenPos < 0)
+        state.firstParenPos = state.scopes.length;
+      state.scopes.push('(');
+      state.charsAdvanced += match[1].length;
+    }
+    if (currentScope(state) == '(' && stream.match(/^\)/)) {
+      state.scopes.pop();
+      state.charsAdvanced += 1;
+      if (state.scopes.length <= state.firstParenPos) {
+        var isDefinition = stream.match(/^\s*?=(?!=)/, false);
+        stream.backUp(state.charsAdvanced);
+        state.firstParenPos = -1;
+        state.charsAdvanced = 0;
+        if (isDefinition)
+          return 'def';
+        return 'builtin';
+      }
+    }
+    // Unfortunately javascript does not support multiline strings, so we have
+    // to undo anything done upto here if a function call or definition splits
+    // over two or more lines.
+    if (stream.match(/^$/g, false)) {
+      stream.backUp(state.charsAdvanced);
+      while (state.scopes.length > state.firstParenPos + 1)
+        state.scopes.pop();
+      state.firstParenPos = -1;
+      state.charsAdvanced = 0;
+      return 'variable';
+    }
+    state.charsAdvanced += stream.match(/^([^()]*)/)[1].length;
+    return callOrDef(stream, state);
+  }
+
   function tokenStringFactory(delimiter) {
-    while ('rub'.indexOf(delimiter.charAt(0).toLowerCase()) >= 0) {
+    while ('bruv'.indexOf(delimiter.charAt(0).toLowerCase()) >= 0) {
       delimiter = delimiter.substr(1);
     }
-    var singleline = delimiter.length == 1;
+    var singleline = delimiter == "'";
     var OUTCLASS = 'string';
 
     function tokenString(stream, state) {
@@ -274,9 +326,14 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {
     var style = state.tokenize(stream, state);
     var current = stream.current();
 
+    if (current && style) {
+      state.lastToken = current;
+    }
+
     // Handle '.' connected identifiers
     if (current === '.') {
-      style = stream.match(identifiers, false) ? null : ERRORCLASS;
+      style = stream.match(identifiers, false) ||
+              stream.match(macro, false) ? null : ERRORCLASS;
       if (style === null && state.lastStyle === 'meta') {
           // Apply 'meta' style to '.' connected identifiers when
           // appropriate.
@@ -284,7 +341,6 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {
       }
       return style;
     }
-
     return style;
   }
 
@@ -293,7 +349,11 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {
       return {
         tokenize: tokenBase,
         scopes: [],
-        leaving_expr: false
+        lastToken: null,
+        leavingExpr: false,
+        isDefinition: false,
+        charsAdvanced: 0,
+        firstParenPos: -1
       };
     },
 
@@ -305,7 +365,7 @@ CodeMirror.defineMode("julia", function(_conf, parserConf) {
 
     indent: function(state, textAfter) {
       var delta = 0;
-      if (textAfter=="end" || textAfter=="]" || textAfter=="}" || textAfter=="else" || textAfter=="elseif" || textAfter=="catch" || textAfter=="finally") {
+      if (textAfter == "end" || textAfter == "]" || textAfter == "}" || textAfter == "else" || textAfter == "elseif" || textAfter == "catch" || textAfter == "finally") {
         delta = -1;
       }
       return (state.scopes.length + delta) * _conf.indentUnit;
-- 
GitLab