The close brace does not always get inserted now. First a simple check takes place to see if a matching close
brace might already exist. This allows you to add a new line to the beginning of an existing block by typing enter
at the open brace without an additional new brace getting inserted.
The function bound to return now also tries to detect if current line has a unterminated string and assumes you are
trying to enter a multi line string. It adds a java newline char, closes the string, and appends it to a new string
that starts on the next line.
This behavior is controlled by the variables jde-gen-embrace and jde-gen-complete-multi-line-string.
I also modified the jde-indent-after-yank code that was posted here some time ago to let you paste
multiline strings.
It's been tested on both XEmacs also and I've been using it for the last few days so hopefully it should
be reasonably bug-free.
(defvar jde-gen-embrace t "Typing enter after a close brace at the end of a line will insert a matching closing brace (if required) and put point on a empty line between the braces and indent the new lines.
So if before you had:
pubic void function () {
^
You now have:pubic void function () {
} ^
Point must be at the end of the line, or at a } character followed by the end of the line.
If it thinks a matching close brace already exists a new one is not inserted.
Before:
pubic void function () {
} ^
After:
pubic void function () {
} ^
It does this by checking if the line containing the matching close brace is already correctly indented. If it is not then this close brace probabaly does not match the open brace at point and so a new close brace is inserted.")
(defvar jde-gen-complete-multi-line-string t
"Typing enter at the end of a line with an unterminated string
constant will result in the generation of the required string by
adding a \\n character to the end of the line, closing the string,
adding the string append operator (+) and starting a new string
on the next line. Before:
String a = \"This is a multi-line string
^
After:
String a = \"This is a multi-line string\\n\" +
\"
^")
(defun jde-line-end-at-open-brace ()
(and (= (preceding-char) ?{) (looking-at "}?$")))(defun jde-gen-embrace () "Adds a new line and inserts a matching close brace if required. See variable 'jde-gen-embrace.
Assumes that 'jde-line-end-at-open-brace has been called and it
returned true."
(interactive)
(let ((open-indent (current-indentation)))
(when (looking-at "}")
;; if there is a } after point, put it on a new line and come back
(newline-and-indent)
(end-of-line 0) ;; move to end of previous line
)
;; make a blank line
(newline-and-indent)
;; Look for the matching close brace; if it is indented at the
;; level as the open brace or if indent-according-to-mode thinks
;; it is correctly indented, don't add a new close brace.
(unless (save-excursion
(condition-case err
(progn
(up-list 1)
(let* ((old-close-indent (current-indentation))
(dummy (indent-according-to-mode))
(new-close-indent (current-indentation))
;; save return value
(ret (and (= (preceding-char) ?})
(or (= open-indent old-close-indent) (= old-close-indent new-close-indent)))))
;; set indent back to what it was
(indent-line-to old-close-indent)
;; return result
ret
))
(error nil)))
;; add the } on a new indented line
(insert "}")
(c-indent-line)
(end-of-line 0) ;; move to end of previous line
(newline-and-indent))))
(defun jde-line-has-incomplete-string ()
"Returns true if point is at the end of the line and the
current line has a mismatched doublequote character."
(let* ((end (point))
(beg (save-excursion (beginning-of-line) (point)))
(count 0))
(save-excursion
(while (search-backward "\"" beg t)
(unless (or (= (preceding-char) ?\\) (and (= (preceding-char) ?') (looking-at "\"'")))
(incf count)
)
))
(= (mod count 2) 1)
))
(defun jde-multi-line-string-enter ()
"Ends an unterminated string constant and coninues it on the
next line. See variable 'jde-gen-complete-multi-line-string.
Assumes that 'jde-line-has-incomplete-string was called and it returned true. "
(interactive)
(insert "\\n\" +")
(newline-and-indent)
(insert "\"")
)
(defun jde-mode-return ()
"Check if variables 'jde-gen-embrace or
'jde-gen-complete-multi-line-string are set and handle them
appropriately."
(interactive)
(cond
((and jde-gen-complete-multi-line-string (jde-line-has-incomplete-string))
(jde-multi-line-string-enter))
((and jde-gen-embrace (jde-line-end-at-open-brace))
(jde-gen-embrace))
(t (newline-and-indent)))
)
(define-key jde-mode-map [return] 'jde-mode-return)
;; Do an indent after a yank. (defadvice yank (after jde-indent-and-fix-strings-after-yank activate) (jde-indent-and-fix-strings-after-yank))
(defadvice yank-pop (after jde-indent-and-fix-strings-after-yank activate) (jde-indent-and-fix-strings-after-yank))
(lexical-let ((unescaped-quote (if (string-match "XEmacs" (version)) ;; no sregex in XEmacs
"\\(?:[^\\]\\|^\\)\""
(require 'sregex)
(sregexq (or
;; the " char should either have
;; something that's not a \ before it
(not-char ?\\)
;; or should be at the beginning of the line
bol)
"\""))))
(defun jde-indent-and-fix-strings-after-yank ()
"Do an indent and also check if adding a multiline string after a yank"
(when (equal "JDE" mode-name)
(let ((transient-mark-mode nil) (zmacs-regions nil))
;; check for incomplete string
(save-excursion
(exchange-point-and-mark)
(when (and jde-gen-complete-multi-line-string (jde-line-has-incomplete-string))
(save-restriction
(narrow-to-region (region-beginning) (region-end))
;; escape open quotes
(while (re-search-forward unescaped-quote nil t)
(backward-char)
(insert "\\"))
(goto-char (point-min))
;; for each line added terminate the string on the
;; previous line and open a new string
(while (progn (end-of-line) (not (= (point) (point-max))))
(insert "\\n\" +")
(forward-char)
(insert "\"")
)
)
(indent-according-to-mode)
))
(indent-region (region-beginning) (region-end) nil)
(end-of-line)
))))
;; to remove the above advice:
;; (ad-remove-advice 'yank 'after 'jde-indent-and-fix-strings-after-yank)
;; (ad-remove-advice 'yank-pop 'after 'jde-indent-and-fix-strings-after-yank)
Suraj
