branch: elpa/j-mode
commit 5dca69ca557310104fcca1e86960c261857f2f21
Author: LdBeth <andp...@foxmail.com>
Commit: LdBeth <andp...@foxmail.com>

    Improved string handling
    
    Added font lock for multi-line string. Changed one line string
    font lock behavior so an open quote does not span multiple
    lines.
---
 j-console.el   | 13 ++++++++-
 j-font-lock.el | 84 ++++++++++++++++++++++++++++++++++++++++++++++++----------
 j-mode.el      | 16 ++++++-----
 3 files changed, 92 insertions(+), 21 deletions(-)

diff --git a/j-console.el b/j-console.el
index 7998205e37..fa28fce342 100644
--- a/j-console.el
+++ b/j-console.el
@@ -128,7 +128,7 @@ the containing buffer"
         (session (j-console-ensure-session)))
     (pop-to-buffer (process-buffer session))
     (goto-char (point-max))
-    (insert (format "\n%s\n" region))
+    (insert (format "%s" region))
     (comint-send-input)))
 
 (defun j-console-execute-line ()
@@ -141,6 +141,17 @@ the containing buffer"
   (interactive)
   (j-console-execute-region (point-min) (point-max)))
 
+;;XXX should maybe check that we are indeed in an explicit def, unlike
+;;elisp counterpart
+(defun j-console-execute-definition ()
+  "Send the current explicit definition to a running J session."
+  (interactive)
+  (save-excursion
+    (mark-defun)
+    (let ((start (point))
+          (end (mark)))
+      (j-console-execute-region start end))))
+
 (provide 'j-console)
 
 ;;; j-console.el ends here
diff --git a/j-font-lock.el b/j-font-lock.el
index 18bee08b70..4ecfb576fe 100644
--- a/j-font-lock.el
+++ b/j-font-lock.el
@@ -88,19 +88,61 @@
     ;; (modify-syntax-entry ?\: "_"   table)
     (modify-syntax-entry ?\( "()"  table)
     (modify-syntax-entry ?\) ")("  table)
-    (modify-syntax-entry ?\' "\""  table)
-    (modify-syntax-entry ?N "w 1"  table)
-    (modify-syntax-entry ?B "w 2"  table)
+    (modify-syntax-entry ?\' "."  table)
+    ;; (modify-syntax-entry ?N "w 1"  table)
+    ;; (modify-syntax-entry ?B "w 2"  table)
     (modify-syntax-entry ?\n ">"   table)
-    (modify-syntax-entry ?\r ">"   table)
+    ;; (modify-syntax-entry ?\r ">"   table)
     table)
   "Syntax table for j-mode")
 
 (defalias 'j-mode-syntax-propertize
   (syntax-propertize-rules
-   ("^\\()\\)" (1 "."))
+   ("\\(N\\)\\(B\\)\\." (1 "w 1") (2 "w 2"))
+   ("\\(?:0\\|noun\\)\s+\\(?::\s*0\\|define\\)"
+    (0 (j-font-lock-multiline-string ?:)))
+   ("^\\()\\)" (1 (j-font-lock-multiline-string ?\))))
+   ("{{)n" (0 (j-font-lock-multiline-string ?\{)))
+   ("}}" (0 (j-font-lock-multiline-string ?\})))
    ("{{\\()\\)" (1 "."))
-   ("\\('\\)`?[0-9A-Z_a-z ]*\\('\\)\s*=[.:]" (1 ".") (2 "."))))
+   ("\\('\\)`?[0-9A-Z_a-z ]*\\('\\)\s*=[.:]" (1 ".") (2 "."))
+   ("\\('\\)\\(?:[^'\n]\\|''\\)*\\('\\)" (1 "\"") (2 "\""))))
+
+(defun j-font-lock-multiline-string (arg)
+  (pcase arg
+    (?: (let* ((ppss (save-excursion (backward-char 2) (syntax-ppss)))
+               (string-start (and (eq t (nth 3 ppss)) (nth 8 ppss)))
+               (eol (pos-eol)))
+          (unless string-start
+            (put-text-property eol (1+ eol)
+                               'syntax-table (string-to-syntax "|")))
+          nil))
+    (?\{ (let* ((ppss (save-excursion (backward-char 4) (syntax-ppss)))
+               (string-start (and (eq t (nth 3 ppss)) (nth 8 ppss)))
+               (quote-starting-pos (- (point) 4)))
+          (unless string-start
+            (put-text-property quote-starting-pos (1+ quote-starting-pos)
+                               'syntax-table (string-to-syntax "|"))
+            (put-text-property (+ 2 quote-starting-pos) (+ 3 
quote-starting-pos)
+                               'syntax-table (string-to-syntax ".")))
+          nil))
+    (?\) (let* ((ppss (save-excursion (backward-char 2) (syntax-ppss)))
+                (string-start (and (eq t (nth 3 ppss)) (nth 8 ppss)))
+                (quote-starting-pos (- (point) 1)))
+           (if (and string-start (eql (char-after string-start)
+                                      ?\n))
+               (put-text-property (1- quote-starting-pos) quote-starting-pos
+                                  'syntax-table (string-to-syntax "|")))
+           (string-to-syntax ".")))
+    (?\} (let* ((ppss (save-excursion (backward-char 2) (syntax-ppss)))
+                (string-start (and (eq t (nth 3 ppss)) (nth 8 ppss)))
+                (quote-end-pos (point)))
+           (if (and string-start (eql (char-after string-start)
+                                      ?\{))
+               (put-text-property (1- quote-end-pos) quote-end-pos
+                                  'syntax-table (string-to-syntax "|")))
+           nil))))
+
 
 (defvar j-font-lock-constants
   '(
@@ -174,11 +216,11 @@
   (append j-font-lock-len-3-others j-font-lock-len-2-others 
j-font-lock-len-1-others))
 
 (defvar j-font-lock-len-3-conjunctions
-  '("&.:" "F.." "F.:" "F:." "F::" " ::" " :."))
+  '("&.:" "F.." "F.:" "F:." "F::"))
 (defvar j-font-lock-len-2-conjunctions
   '("t." "S:" "L:" "H." "D:" "D." "d." "F." "F:" "m."
     "&:" "&." "@:" "@." "`:" "!:" "!." ";." "[." "]."
-    "^:" " ." " :"))
+    "^:"))
 (defvar j-font-lock-len-1-conjunctions
   '("&" "@" "`" "\""))
 (defvar j-font-lock-conjunctions
@@ -237,21 +279,35 @@
     (,(regexp-opt j-font-lock-len-1-verbs) . 'j-verb-face)
     (,(regexp-opt j-font-lock-len-1-adverbs) . 'j-adverb-face)
     (,(regexp-opt j-font-lock-len-1-conjunctions) . 'j-conjunction-face)
+    (,(rx (or bol (+ "\s")) (group (or ":" "." ":." "::")))
+     (1 'j-conjunction-face))
     ;;(,(regexp-opt j-font-lock-len-1-others) . 'j-other-face)
     )
   "J Mode font lock keys words")
 
+(defun j-font-lock-docstring-p (state)
+  "Detect if multi-line string should be docstring."
+  (save-excursion
+    (goto-char (nth 8 state))
+    (beginning-of-line)
+    (not (looking-at-p "[_'`a-zA-Z0-9\s]+=[.:]"))))
+
 (defun j-font-lock-syntactic-face-function (state)
   "Function for detection of string vs. Comment. Note: J comments
 are three chars longs, there is no easy / evident way to handle
 this in emacs and it poses problems"
-  (if (nth 3 state) font-lock-string-face
-    (let* ((start-pos (nth 8 state)))
-      (and (<= (+ start-pos 3) (point-max))
-           (eq (char-after start-pos) ?N)
+  (let* ((start-pos (nth 8 state)))
+    (cond
+     ((nth 3 state) (if (and
+                         (eql (char-after start-pos) ?\n)
+                         (j-font-lock-docstring-p state))
+                        font-lock-doc-face
+                      font-lock-string-face))
+     ((and (<= (+ start-pos 3) (point-max))
+           (eql (char-after start-pos) ?N)
            (string= (buffer-substring-no-properties
                      start-pos (+ start-pos 3))
-                    "NB.")
-           font-lock-comment-face))))
+                    "NB."))
+      font-lock-comment-face))))
 
 (provide 'j-font-lock)
diff --git a/j-mode.el b/j-mode.el
index 1cc0ea7de5..3f2743cb03 100644
--- a/j-mode.el
+++ b/j-mode.el
@@ -82,6 +82,7 @@
                        "for.")))
                    (seq (or "for" "goto" "label")
                         (regexp "_[a-zA-Z]+\\."))))
+          (seq bol ":" eol)
           (seq (regexp "[_a-zA-Z0-9]+") (? "'")
                (* "\s") "=" (or "." ":") (* "\s")
                (or "{{"
@@ -151,15 +152,16 @@ contents of current line."
       (back-to-indentation)
       (let* ((tentative-indent (j-compute-indentation))
              ;;FIXME doesn't handle comments correctly
-             (indent (if (looking-at j-dedenting-keywords-regexp)
-                         (max 0 (- tentative-indent j-indent-offset))
-                         tentative-indent))
+             (indent (cond
+                      ((looking-at j-dedenting-keywords-regexp)
+                       (max 0 (- tentative-indent j-indent-offset)))
+                      ((looking-at ":") 0)
+                      (t tentative-indent)))
              (delta (- indent (current-indentation))))
 ;;         (message "###DEBUGi:%d t:%d" indent tentative-indent)
         (indent-line-to indent)
         (back-to-indentation)
-        (goto-char (max (point) (+ old-point delta))))
-      )))
+        (goto-char (max (point) (+ old-point delta)))))))
 
 (defun j-which-explict-definition ()
   "Return nil, `:one-liner' or `:multi-liner' depending on what
@@ -220,6 +222,7 @@ contents of current line."
     (define-key map (kbd "C-c C-c") 'j-console-execute-buffer)
     (define-key map (kbd "C-c C-r") 'j-console-execute-region)
     (define-key map (kbd "C-c C-l") 'j-console-execute-line)
+    (define-key map (kbd "C-M-x")   'j-console-execute-definition)
     (define-key map (kbd "C-c h")   'j-help-lookup-symbol)
     (define-key map (kbd "C-c C-h") 'j-help-lookup-symbol-at-point)
     map)
@@ -232,6 +235,7 @@ contents of current line."
     ["Execute Buffer" j-console-execute-buffer t]
     ["Execute Region" j-console-execute-region t]
     ["Execute Line" j-console-execute-line t]
+    ["Execute Definition" j-console-execute-definition t]
     "---"
     ["J Symbol Look-up" j-help-lookup-symbol t]
     ["J Symbol Dynamic Look-up" j-help-lookup-symbol-at-point t]
@@ -256,7 +260,7 @@ contents of current line."
               beginning-of-defun-function #'j-beginning-of-explicit-definition
               end-of-defun-function       #'j-end-of-explicit-definition
               font-lock-comment-start-skip
-              "NB. *"
+              "NB\\. *"
               font-lock-defaults
               '(j-font-lock-keywords
                 nil nil nil nil

Reply via email to