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